Vapor Mode sắp tới của Vue 3.6 sẽ được phát hành vào mùa thu này, và nó thực hiện một điều mà framework này chưa từng làm trước đây: nó biên dịch các single-file component thành các bản cập nhật trực tiếp vào DOM, hoàn toàn bỏ qua virtual DOM.

Tại sao Vue lại quay lưng với virtual DOM

Kể từ Vue 2, virtual DOM đã là cốt lõi trong mô hình reactivity của framework. Khi trạng thái (state) thay đổi, Vue sẽ xây dựng một cây trong bộ nhớ nhẹ, so sánh (diff) nó với phiên bản trước đó, và chỉ vá (patch) những phần có sự khác biệt. Sự gián tiếp này cho phép các nhà phát triển viết mã khai báo (declarative code) mà không cần lo lắng về việc phần tử nào thực sự cần được cập nhật. Sự đánh đổi là mỗi lần render vẫn phải trả giá bằng việc xây dựng và so sánh cây virtual đó.

Vapor Mode loại bỏ bước trung gian đó. Trong quá trình build, trình biên dịch Vue sẽ phân tích template và tạo ra JavaScript gọi trực tiếp các phương thức DOM gốc—element.textContent = …, element.setAttribute(...)—ngay tại nơi cần thay đổi. Không có virtual node nào được tạo ra, không có vòng lặp diffing nào chạy. Kết quả là bundle chỉ chứa mã cần thiết cho các bản cập nhật cụ thể mà bạn đã viết, cộng với runtime cần thiết cho reactivity.

Tác động thực tế đến kích thước và tốc độ

  • Kích thước bundle – Bằng cách loại bỏ runtime virtual-DOM và các cấu trúc dữ liệu của nó, mã được tạo ra sẽ nhỏ gọn hơn. Trong các dự án có lưới (grid) hoặc canvas lớn cập nhật hàng chục lần mỗi giây, những khoản tiết kiệm đó sẽ tích tụ lại, đặc biệt là trên các kết nối băng thông thấp.
  • Hiệu năng – Các lệnh gọi DOM trực tiếp giúp bỏ qua chi phí xử lý diffing, điều này trở nên rõ rệt khi UI thay đổi với tần suất cao. Trong một bộ trò chơi trình duyệt cá nhân—một trò nonogram, một bản clone trò chơi dò mìn, và một trình trực quan hóa khối Rubik 3D—tôi đã tự viết logic rendering bằng tay, chỉ cập nhật DOM ở những nơi thực sự cần thiết.
  • Sự tiện dụng cho lập trình viên – Trình biên dịch sẽ đảm nhận phần việc nặng nhọc nhất. Bạn vẫn viết các template Vue thông thường; bạn không cần phải tự tay viết các lệnh document.querySelector. Mã được tạo ra phản ánh chính xác cách tiếp cận viết bằng tay đã mang lại cho tôi hiệu năng tốt nhất trong các trò chơi đó.

Khi nào Vapor Mode thực sự hữu ích

  1. Cập nhật tần suất cao trên các cấu trúc lớn – Các trò chơi, dashboard thâm dụng dữ liệu, hoặc bất kỳ giao diện nào vẽ lại nhiều ô (cell) trong mỗi tick đều được hưởng lợi nhiều nhất. Việc diffing một lưới lớn trong mỗi tick có thể chiếm hết ngân sách khung hình (frame budget); các bản cập nhật trực tiếp giúp công việc diễn ra tuyến tính và có thể dự đoán được.
  2. Triển khai bị giới hạn về kích thước bundle – Các trang web ưu tiên thiết bị di động (mobile-first) vốn phải tải dưới vài trăm kilobyte sẽ thấy sự sụt giảm kích thước rõ rệt khi runtime virtual-DOM biến mất.
  3. Trạng thái thuần khiết và có thể dự đoán – Vapor Mode giả định rằng bạn giữ trạng thái bất biến (immutable) và coi DOM như một sự phản chiếu thuần khiết của trạng thái đó. Nếu mã của bạn trộn lẫn các side-effects hoặc làm thay đổi (mutate) DOM bên ngoài hệ thống reactivity của Vue, các bản cập nhật được tạo ra có thể bị mất đồng bộ, gây ra lỗi hiển thị.

Nơi phương pháp cũ vẫn chiếm ưu thế

  • Các UI có tần suất thấp – Các form đơn giản, trang tĩnh, hoặc bảng điều khiển admin chỉ render lại khi có hành động thỉnh thoảng từ người dùng thì hiệu năng tăng thêm không đáng kể. Công việc bổ sung để xây dựng một cây virtual là không đáng kể so với độ trễ mạng hoặc thời gian xử lý của máy chủ.
  • Hệ thống phân cấp component phức tạp – Khi một cây sâu chỉ thay đổi một nút lá (leaf node), virtual DOM có thể tự động bỏ qua các phần lớn của cây. Các bản cập nhật trực tiếp buộc trình biên dịch phải tạo ra các bản vá chính xác cho mỗi thay đổi có thể xảy ra, điều này có thể làm tăng kích thước mã trong các trường hợp biên.
  • Công cụ và hệ sinh thái – Nhiều plugin Vue, devtools và tiện ích kiểm thử được kết nối với lớp virtual-DOM. Những tích hợp đó có thể cần được cập nhật để hoạt động với các component chạy Vapor-mode cho đến khi hệ sinh thái bắt kịp.

Những điều cần theo dõi tiếp theo

  • Bản phát hành ổn định – Vue 3.6 hiện đang ở trạng thái release-candidate. Nhóm phát triển dự kiến sẽ ra mắt bản ổn định cuối cùng vào mùa thu này. Những người muốn áp dụng sớm nên đợi phiên bản đó trước khi triển khai mã lên môi trường production.
  • Lộ trình chuyển đổi – Các dự án Vue hiện tại có thể chọn sử dụng Vapor Mode trên cơ sở từng component riêng lẻ.
  • Công cụ đo hiệu năng – Các bài kiểm tra benchmark so sánh giữa bản build virtual-DOM và Vapor-mode trên các ứng dụng thực tế sẽ giúp các đội ngũ quyết định khi nào sự đánh đổi này là xứng đáng.

Tóm lại

Vapor Mode mang đến cho các nhà phát triển Vue những gì tốt nhất từ cả hai thế giới: cú pháp khai báo mà họ yêu thích và tốc độ thuần túy của các bản cập nhật DOM được viết thủ công. Nó phát huy thế mạnh trong các ứng dụng cần làm mới các phần lớn của UI nhiều lần mỗi giây và trong các đợt triển khai mà mỗi kilobyte đều quan trọng. Đối với các giao diện có lưu lượng truy cập thấp, virtual DOM truyền thống vẫn là một lựa chọn đơn giản và hoàn toàn khả thi. Khi tính năng này chuyển từ bản release candidate sang bản ổn định, cộng đồng Vue sẽ cần cân nhắc giữa việc tiết kiệm kích thước bundle với mức độ sẵn sàng của hệ sinh thái và đặc thù hiệu năng cụ thể của các ứng dụng của họ.