Hiểu cách trình duyệt (Chrome, Safari, Firefox) vẽ trang web là kiến thức cốt lõi để tối ưu hóa hiệu năng (Performance Optimization).
1. Kiến trúc trình duyệt (Browser Architecture)
Trình duyệt hiện đại là một OS thu nhỏ với nhiều process:
- Browser Process (Main): Quản lý thanh địa chỉ, nút back/forward, tab strip.
- Renderer Process: Vẽ nội dung tab (Mỗi tab thường là 1 process riêng để isolated).
- GPU Process: Xử lý đồ họa.
- Network Process: Tải tài nguyên.
2. Critical Rendering Path (CRP)
Khi Renderer Process nhận HTML, nó thực hiện các bước sau:
Bước 1: Parsing HTML -> DOM Tree
- Trình duyệt đọc các byte, chuyển thành ký tự, token, node và cuối cùng là cây DOM (Document Object Model).
- Lưu ý: Nếu gặp thẻ
<script>, parser sẽ DỪNG LẠI để tải và chạy JS (trừ khi cóasynchoặcdefer). Đây là lý do ta để script ở cuối body.
Bước 2: Parsing CSS -> CSSOM Tree
- Giống DOM nhưng cho CSS (CSS Object Model).
- Browser phải tính toán style cho từng node (kế thừa, override).
- CSS là Render Blocking Resource (Trình duyệt sẽ không vẽ gì cho đến khi CSSOM xong để tránh Flash of Unstyled Content).
Bước 3: Render Tree
- Render Tree = DOM + CSSOM.
- Chỉ chứa các node hiển thị được (Visible).
- Node
display: nonesẽ KHÔNG có trong Render Tree. - Node
visibility: hiddenVẪN CÓ trong Render Tree (nhưng không thấy).
Bước 4: Layout (Reflow)
- Tính toán vị trí (x, y) và kích thước (width, height) của từng node trên viewport.
- Reflow rất tốn kém (Expensive). Nó xảy ra khi:
- Thêm/xóa DOM.
- Resize cửa sổ.
- Thay đổi kích thước/font chữ.
- Đọc các thuộc tính layout (
offsetWidth,scrollTop...).
Bước 5: Paint
- Điền pixel vào các ô đã tính toán (màu sắc, hình ảnh, border).
Bước 6: Composite (Hardware Acceleration)
- Tách trang thành các lớp (Layers) riêng biệt.
- GPU sẽ ghép các layer lại.
- Tối ưu: Sử dụng
transformvàopacitycho animation vì nó chỉ kích hoạt Composite, không gây Reflow/Paint.
3. JavaScript Engine (V8)
Chrome sử dụng V8 Engine (C++). Quy trình:
- Parser: Đọc code JS -> Abstract Syntax Tree (AST).
- Ignition (Interpreter): Chạy code AST (Bytecode).
- TurboFan (Compiler): Tối ưu hóa các đoạn code chạy nhiều lần (Hot path) thành Machine Code.
Event Loop
JS là đơn luồng (Single-threaded). Event Loop giúp nó xử lý bất đồng bộ (Async).
- Call Stack: Code đang chạy.
- Web APIs: (setTimeout, fetch, DOM event).
- Task Queue (Callback Queue): Chờ Call Stack rỗng thì nhảy vào.
- Microtask Queue: (Promise, queueMicrotask). Ưu tiên cao hơn Task Queue.
Kết luận
Để tối ưu Rendering:
- Giảm DOM size.
- Hạn chế Reflow (Layout Thrashing).
- Dùng
transformcho Animation. - Defer non-critical JS.