Cách đo chiều cao Bubble Chat mà không gây Reflow: Pretext vs CellMeasurer

05 tháng 4, 2026·4 phút đọc

Khi xây dựng giao diện chat với React Virtualization, việc đo chiều cao các khối tin nhắn mà không gây ra reflow (thay đổi layout) là bài toán khó. Bài viết này so sánh hai phương pháp: CellMeasurer sử dụng DOM và Pretext sử dụng Canvas để tính toán trước, chỉ ra sự khác biệt về hiệu suất và chi phí render.

Cách đo chiều cao Bubble Chat mà không gây Reflow: Pretext vs CellMeasurer

Khi phát triển ứng dụng web, đặc biệt là các ứng dụng chat, việc sử dụng React Virtualization là bắt buộc để đảm bảo hiệu suất khi xử lý hàng nghìn tin nhắn. Tuy nhiên, có một rào cản lớn: các trình ảo hóa này cần biết chiều cao của từng item trước khi chúng được vẽ ra màn hình. Browser có thể trả lời câu hỏi này, nhưng cách hỏi đó thường tốn kém chi phí reflow (thay đổi layout).

Bài viết này sẽ so sánh hai giải pháp phổ biến: CellMeasurer (từ react-virtualized) và Pretext (từ react-window), giúp bạn hiểu rõ sự khác biệt về hiệu suất thực tế.

Vấn đề cốt lõi

Tính năng ảo hóa hoạt động bằng cách không vẽ các item nằm ngoài màn hình, giúp danh sách trượt mượt mà. Tuy nhiên, nó yêu cầu bạn cung cấp chiều cao của từng item ngay từ đầu. Với các bong bóng tin nhắn chat, chiều cao không cố định mà phụ thuộc vào độ dài văn bản, cách xuống dòng và chiều rộng container. Do đó, bạn buộc phải đo chiều cao trước khi render.

  • CellMeasurer: Cách tiếp cận truyền thống, nó vẽ item vào DOM và đọc chiều thật của nó thông qua getBoundingClientRect.
  • Pretext: Cách tiếp cận mới hơn, nó sử dụng Canvas để đo chiều cao tính toán toán học, không chạm vào DOM.

Cách thức hoạt động của từng phương pháp

CellMeasurer (react-virtualized)

const cache = new CellMeasurerCache({ fixedWidth: true, defaultHeight: 60 });
// ...

Phương pháp này hoạt động bằng cách tạo ra một bản đồ bộ nhớ đệm (cache) để lưu trữ chiều cao đã đo. Khi render, nó sử dụng getBoundingClientRect để lấy chiều cao thực tế của dòng tin nhắn vừa xuất hiện trong màn hình. Mặc dù chính xác, cách này buộc trình duyệt phải thực hiện reflow mỗi khi đo chiều cao cho một dòng mới.

Pretext (react-window)

import { prepare, layout } from "@chenglou/pretext";
// ...
const { height } = layout(msg.prepared, containerWidth * 0.5, LINE_HEIGHT);

Pretext làm việc theo hai bước:

  1. prepare(): Chia nhỏ văn bản và đo chiều cao sử dụng Canvas một lần duy nhất khi tin nhắn được tải.
  2. layout(): Tính toán chiều cao bằng toán học thuần túy (pure arithmetic) khi cần hiển thị hoặc thay đổi kích thước màn hình.

So sánh hiệu suất

Dưới đây là kết quả đo lường khi cuộn qua 200 tin nhắn (chúng ta chỉ vẽ khoảng 10 item cùng lúc).

Sự kiện buộc layout (Layout Forced events)

  • CellMeasurer: Khoảng 10 lần mỗi lần cuộn (lazy measurement). Mỗi khi một dòng mới xuất hiện trong tầm nhìn, nó sẽ gây ra một lần reflow.
  • Pretext: 0 lần reflow. Không bao giờ có sự thay đổi layout, bất kể bạn đang cuộn hay thay đổi kích thước màn hình.

Thời gian tính toán (Scripting time)

  • CellMeasurer: Chi phí thấp sau lần đo đầu tiên, nhưng vẫn phải trả chi phí mỗi khi vẽ một dòng mới.
  • Pretext: layout() cực nhanh (toán học thuần túy). prepare() chạy một lần khi tin nhắn đến (thường là khi tải dữ liệu), sau đó không tốn nhiều chi phí khi render.

Độ chính xác

Cả hai phương pháp đều chính xác 100%. Sự khác biệt nằm ở hiệu suất, không phải độ chính xác.

Khi nào nên dùng?

Sử dụng CellMeasurer nếu:

  • Bạn đang sử dụng thư viện react-virtualized và muốn tích hợp nhanh chóng.
  • Bạn không muốn tự viết logic đo chiều cao.
  • Người dùng hiếm khi thay đổi kích thước màn hình trong quá trình tương tác.

Sử dụng Pretext nếu:

  • Hiệu suất ban đầu (initial load) là ưu tiên hàng đầu.
  • Giao diện hỗ trợ văn bản không phải tiếng Latinh (như tiếng Nhật, Trung, Hàn) và emoji.
  • Giao diện phải phản hồi tốt khi người dùng thay đổi kích thước màn hình (responsive).

Kết luận

Cả CellMeasurer và Pretext đều giải quyết vấn đề đo chiều cao chat bubble chính xác. Tuy nhiên, Pretext là lựa chọn tốt hơn về mặt kỹ thuật vì nó loại bỏ hoàn toàn chi phí reflow. CellMeasurer vẫn hữu ích trong các trường hợp đơn giản, nhưng nếu bạn đang xây dựng một ứng dụng chat chuyên nghiệp, Pretext mang lại trải nghiệm mượt mà hơn.

Bài viết được tổng hợp và biên soạn bằng AI từ các nguồn tin tức công nghệ. Nội dung mang tính tham khảo. Xem bài gốc ↗