0

Từ Zero đến Principal Frontend Engineer (P10): Bật Mí Mấy Chiêu Render - Tới Cả Trình Duyệt Cũng Phải Gật Gù

Ở phần 5, tụi mình đã nói chuyện về tư duy performance nói chung rồi. Giờ đến phần "động trời" hơn nè: cách để app của mình render cái "uỵch" một cái là xong, mượt mà ko chê vào đâu được.

Làm Principal Engineer rồi, mình không thể chỉ dừng ở việc biết xài useMemo, useCallback đâu. Mình phải hiểu sâu tới mức biết tại sao dùng nó, và có những cách còn hay ho hơn nữa để cả bộ framework mình đang xài cũng phải "cúi đầu thán phục".

Bài này, mình cùng lật tung mấy bí kíp render để app chạy nhanh vèo vèo nha.

1. Trước Tiên, Phải Hiểu Trình Duyệt Nó Làm Cái Gì

Nghĩ đơn giản thôi: mỗi lần bạn lướt web, trình duyệt nó như một ông thợ xây siêu tốc. Ông ấy phải làm y chang 5 bước sau cho mỗi lần thay đổi:

  1. JavaScript: Ông thợ suy nghĩ xem "à, thằng user này click vô nút này, giờ mình phải làm gì đây?" (ví dụ: tính toán, thay đổi data).
  2. Style (Tính Toán CSS): "Ủa, vậy cái nút này mặc áo màu gì, font chữ ra sao ta?"
  3. Layout (Bố Cục): "Để coi nè, mình đặt cái nút này chỗ nào, to nhỏ cỡ nào, có đè lên thằng khác không?"
  4. Paint (Sơn Vẽ): "Oke, giờ mình tô màu, vẽ viền, trang trí cho nó thật đẹp nào."
  5. Composite (Ghép Hình): "Cuối cùng, ghép cái nút mới vẽ này với mấy thằng khác trên trang để show ra cho user xem."

Bước 3 (Layout)4 (Paint) là 2 bước CỰC KỲ TỐN SỨC. Nhiệm vụ của mình là tránh kích hoạt 2 ông này càng nhiều càng tốt. Thay vì bắt ổng sửa cả bức tường (Layout), mình chỉ cần bảo ổng dán thêm một miếng decal (Composite) lên thôi, sẽ nhanh hơn rất rất nhiều.

2. Đừng Tin Vô Virtual DOM Như Thần Thánh Nữa!

Hồi xưa, ai cũng ca ngợi Virtual DOM (của React, Vue 2) vì nó giúp mình đỡ phải "sờ" vô DOM thật, làm app chạy nhanh hơn. Đúng, nhưng chưa đủ.

Virtual DOM có một nhược điểm lớn: mỗi lần render, nó phải so sánh (diff) 2 cây Virtual DOM để tìm ra chỗ nào khác nhau rồi mới update. Việc so sánh đó cũng ngốn kha khá sức mạnh CPU lắm đó.

Giờ đây, mấy ông framework mới ra trường đã có cách tiếp cận thông minh hơn nhiều:

  • Svelte: Ông này "thông minh từ trong trứng". Lúc bạn build code, Svelte sẽ biên dịch nó thành những dòng lệnh update DOM trực tiếp, gọn như con thoi. State thay đổi là nó biết ngay phải sửa chỗ nào, không cần phải so sánh gì hết. Nhẹ nhàng, nhanh gọn!
  • SolidJS: Ông này chơi hệ "phản ứng" (reactive). Nó xây dựng một mạng lưới kết nối giữa data và UI. Khi data thay đổi, nó trực tiếp đá vô đúng chỗ DOM cần sửa, không vòng vo, không so sánh gì cả. Performance cực khủng.
  • Tương lai của React: Chính React team cũng thấy vấn đề nè. Họ đang phát triển "React Forget" – một cỗ máy sẽ tự động "ghi nhớ" (memoize) giùm bạn, giúp component không re-render một cách ngu ngốc nữa. Đợi ông này ra thì hứa hẹn lắm đây.

Bài học: Đừng ngại thử nghiệm cái mới. Có khi dự án nhỏ, cần performance khủng thì Svelte hay SolidJS lại là lựa chọn đúng đắn đó.

3. Mấy Chiêu Thực Chiến Để App Mượt Mà

a. List Virtualization (Ảo Hóa Danh Sách)
  • Vấn đề: Bạn có 10.000 item trong list. Render hết 10.000 cái? Trình duyệt nó "ngẹt thở" luôn cho coi. Scroll giật như xe hết xăng.
  • Giải pháp: Mình GIẢ VỜ là có 10.000 item, nhưng thực ra chỉ render khoảng 10-20 item đang nằm trong màn hình thôi. Khi user scroll, mình mới lấy item mới để render, item cũ ra khỏi màn hình thì cho "nghỉ hưu".
  • Tool đề cử: Dùng react-window hoặc @tanstack/react-virtual (cái này xịn xò hơn nè).
b. Mẹo Chơi Với React
  • Chia Context nhỏ ra: Đừng nhét hết tất cả state vào một cái Context to đùng. Chia nó ra thành nhiều Context nhỏ, liên quan đến từng phần của app. Vậy thì khi state ở phần A thay đổi, phần B và C sẽ không bị re-render oan.
  • Truyền component làm con: Thay vì truyền data xuống cho component con nó tự render, mình có thể truyền luôn cả một component đã được render sẵn như một prop (ví dụ prop footer). Cách này mình kiểm soát re-render chặt hơn nhiều.
c. Dùng CSS Một Cách "Khôn Ngoan"
  • Animation: Muốn animation mượt? CỨU TINH là 2 thuộc tính transformopacity. 2 ông này rất "rẻ", gần như chỉ tốn sức ở bước Composite thôi. Còn mà bạn dùng width, height, margin để animate thì trình duyệt nó phải tính toán lại layout cả trang, rất tốn sức.
  • content-visibility: auto: Thuộc tính này như bùa hộ mệnh. Nó bảo trình duyệt: "Phần này chưa thấy trên màn hình thì đừng có render làm gì cho mệt. Khi nào scroll tới thì tính sau." Load trang ban đầu nhanh vun vút.
  • will-change: Mình báo trước cho trình duyệt biết: "Ê, sắp tới tao sẽ động vào chỗ này nha, chuẩn bị sẵn đi." Trình duyệt sẽ ưu tiên xử lý, giúp mượt hơn. Nhưng nhớ đừng lạm dụng.

4. Nhớ Luôn Luôn "Đo Đạc"

Nói gì thì nói, phải có bằng chứng. Đừng có đoán mò. Mấy tool này là bạn thân của mình:

  • React DevTools Profiler: Cái này cho mình biết thằng component nào render, render lâu không, và tại sao nó render.
  • Chrome DevTools Performance Tab: Ghi lại toàn bộ quá trình, xem thử frame nào bị giật, thời gian chạy JS có lâu không, có bị Layout hay Paint quá nhiều không.

Tóm Gọn Lại

Mình phải hiểu sâu hơn cái bề mặt của framework. Phải biết cái gì đang xảy ra bên dưới, tại sao nó chậm, và làm sao để sửa.

Nắm được mấy chiêu render này, bạn sẽ tự tin đưa ra quyết định kiến trúc, chọn công nghệ, và tối ưu hóa ứng dụng để mang lại trải nghiệm ngon nhất cho người dùng, dù app có to cỡ nào đi nữa.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí