Hơn một thập kỷ qua, mô hình tư duy khai báo của React luôn gắn liền với một cỗ máy runtime không thể tách rời: Virtual DOM. Vidact, một dự án trình biên dịch viết bằng Rust, vừa tạo nên làn sóng chú ý mới khi chứng minh rằng các component và hook tiêu chuẩn của React hoàn toàn có thể được biên dịch trực tiếp thành các thao tác cập nhật DOM tĩnh mà không cần gửi bất kỳ Virtual DOM hay bộ đối soát nào về trình duyệt.
Bước chuyển dịch cốt lõi trong cơ chế cập nhật
Trong mô hình React truyền thống, tính phản ứng (reactivity) về bản chất là một vòng lặp thực thi runtime. Mỗi khi state thay đổi, React sẽ chạy lại toàn bộ hàm component từ đầu đến cuối, tạo ra một cây phần tử ảo mới, so sánh cây này với cây trước đó thông qua thuật toán đối soát (reconciliation), rồi mới áp dụng các thay đổi tối thiểu lên cây DOM thực tế của trình duyệt. Dù kiến trúc Fiber và các công cụ tối ưu hóa đã giúp quá trình này diễn ra rất nhanh, nhưng chi phí tài nguyên để cấp phát bộ nhớ cho các nút ảo, so khớp object và tải kèm một bộ runtime đồ sộ vẫn là gánh nặng hiện hữu.
Vidact tháo dỡ hoàn toàn vòng lặp tốn kém đó bằng cách chuyển dịch công việc từ runtime sang giai đoạn build-time. Thay vì thực thi liên tục hàm component mỗi khi có biến động dữ liệu, component trong Vidact chỉ chạy đúng một lần duy nhất lúc được gắn vào giao diện (mount). Trong quá trình biên dịch, trình biên dịch quét qua toàn bộ cấu trúc JSX, phân tích chính xác từng mối quan hệ phụ thuộc giữa state và các phần tử hiển thị. Khi state cập nhật, ứng dụng chỉ kích hoạt một hàm cập nhật tĩnh do compiler tạo ra để tác động thẳng vào đúng nút DOM cần thay đổi.
Hãy nhìn vào một component đếm số quen thuộc:
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
Với React thông thường, cú click chuột sẽ gọi lại hàm Counter(), tạo một đối tượng JSX mới để đối soát. Với Vidact, compiler tạo thẻ button một lần duy nhất, gán sự kiện click nguyên bản và gắn kèm một chỉ thị cập nhật chính xác: textNode.data = "Count: " + count. Component không bao giờ bị re-render toàn phần; chỉ có lát cắt DOM tương ứng bị đột biến trực tiếp.
Cỗ máy phân tích Rust hoạt động ra sao?

Để làm được điều này một cách đáng tin cậy, Vidact khai thác hạ tầng phân tích Static Single Assignment (SSA) và High-Level Intermediate Representation (HIR) kế thừa từ hệ thống phân tích của React Compiler chính thức. Được viết hoàn toàn bằng Rust, Vidact phân tích cú pháp JSX, dựng đồ thị luồng điều khiển (Control Flow Graph - CFG) và theo dõi luồng dữ liệu xuyên suốt các phạm vi (scope) của component.
Thông qua việc bóc tách luồng thực thi, Vidact phân loại rõ ràng cấu trúc giao diện thành ba tầng riêng biệt:
- Các cấu trúc DOM tĩnh: Những thẻ HTML và thuộc tính cố định không bao giờ biến đổi sẽ được tạo sẵn một lần và lưu vào bộ nhớ đệm (cache).
- Các điểm ràng buộc động (dynamic bindings): Các text node hoặc thuộc tính gắn với
useStatevà props được ánh xạ trực tiếp tới các hàm cập nhật vi mô chuyên biệt. - Các khối điều khiển có cấu trúc: Các danh sách lặp (
map) hoặc biểu thức điều kiện ba ngôi được biên dịch thành các mốc phạm vi (range markers) và bộ quản lý fragment thay vì tái tạo lại toàn bộ cây component.
Kết quả là gói mã nguồn gửi tới trình duyệt chỉ bao gồm mã JavaScript thuần và một phần runtime siêu nhỏ để hỗ trợ quản lý vòng đời và điều phối sự kiện. Toàn bộ thư viện lõi cồng kềnh của React hoàn toàn biến mất khỏi gói tải trang.
Cái giá của sự thuần khiết: Chấp nhận giới hạn
Việc xây dựng một trình biên dịch loại bỏ Virtual DOM cho React đặt ra bài toán hóc búa về sự dung hòa giữa tính chất động lực học tự do của JavaScript và tính tất định của phân tích tĩnh. Các framework như Svelte hay Solid.js giải quyết bài toán này bằng cách tự định nghĩa cú pháp template hoặc các khối phản ứng riêng biệt (như Signals). Ngược lại, Vidact chọn giữ nguyên cú pháp chuẩn của React, đồng nghĩa với việc phải thiết lập những ranh giới nghiêm ngặt.
Vidact áp dụng triết lý biên dịch dứt khoát: nếu bắt gặp các đoạn mã chứa hành vi động không thể giải quyết hoàn toàn ở bước phân tích tĩnh, quá trình biên dịch sẽ báo lỗi ngay lập tức. Công cụ này kiên quyết từ chối giải pháp chuyển sang cơ chế đối soát runtime chậm chạp để duy trì hiệu năng tuyệt đối.
Điều này đồng nghĩa với việc một số thói quen viết code tự do trong React sẽ không được hỗ trợ:
- Khởi tạo kiểu component động trong runtime mà không thông qua các nhánh rẽ điều kiện tường minh.
- Sử dụng prop spreading (
{...props}) một cách bừa bãi khiến trình biên dịch không thể lần vết thuộc tính. - Dựa dẫm vào các hiệu ứng phụ (side effects) phát sinh tùy tiện ngoài vòng đời
useEffect.
Đối với lập trình viên, đánh đổi này buộc họ phải viết mã có kỷ luật và rõ ràng hơn. Đổi lại, sản phẩm đạt được tốc độ khởi động cực nhanh, loại bỏ hiện tượng giật lag khung hình và tiết kiệm tối đa bộ nhớ trên các thiết bị cấu hình thấp.
Tương lai của kiến trúc Frontend hướng Compiler
Sự xuất hiện của Vidact củng cố một xu hướng tất yếu của ngành kỹ thuật web: ranh giới giữa một thư viện giao diện và một trình biên dịch chuyên sâu đang dần bị xóa nhòa. Khi yêu cầu về tốc độ phản hồi và dung lượng gói mã ngày càng khắt khe, các lớp trừu tượng runtime nặng nề buộc phải nhường chỗ cho trí thông minh ở khâu biên dịch.
Dù Vidact vẫn đang trong giai đoạn thử nghiệm và tiếp tục hoàn thiện tính tương thích với hệ sinh thái phong phú của React, ý tưởng nền tảng của nó đã chứng minh tính khả thi vượt trội. Nó mở ra một tương lai nơi các kỹ sư phần mềm vẫn được tận hưởng sự quen thuộc của tư duy component khai báo mà không còn phải trả giá bằng chi phí vận hành runtime của Virtual DOM.




Đang tải bình luận…