Profiler, memoization và React Compiler
Tối ưu interaction đã đo được, không tối ưu số lần render theo cảm giác. Re-render không đồng nghĩa DOM update; bottleneck có thể nằm ở network, JavaScript, layout, paint, bundle hoặc state ownership.
1. Chẩn đoán đúng tầng
| Triệu chứng | Bằng chứng cần xem | Root cause thường gặp |
|---|---|---|
| Click phản hồi chậm | Browser Performance trace, INP | Long task, render nặng, sync handler |
| Trang hiện chậm | Network waterfall, LCP | Data chain, bundle, image/font |
| Scroll giật | Main-thread/layout/paint trace | Huge list, forced layout, expensive style |
| Nhiều component render | React DevTools Profiler | State/context quá cao, unstable props |
| Layout nhảy | Layout shift track, CLS | Thiếu dimensions, late content |
React Profiler cho biết commit duration, component nào render và interaction nào liên quan. Browser profiler cho biết CPU thực tế đi vào JavaScript, style, layout hay paint. Field metrics phản ánh thiết bị/network user thật; lab benchmark chỉ là controlled evidence.
2. Sửa data flow trước memoization
Colocate transient state, split component để expensive subtree không nhận update vô ích, thu hẹp Context, giữ render pure và tránh Effect chain cập nhật state. Children JSX thường giúp wrapper state không ép toàn subtree render. Dữ liệu server nên dùng cache/selector thay vì copy và fan-out.
- Virtualize hoặc paginate danh sách lớn thay vì render hàng nghìn row.
- Debounce chỉ khi semantics cho phép; transition/deferred value giải quyết render priority, không thay request control.
- Tránh object/function mới lan qua nhiều memoized children nếu identity thực sự quan trọng.
- Không đặt state cao hơn owner chỉ để tiện truy cập.
3. memo, useMemo và useCallback
memo có thể bỏ render khi props so sánh Object.is không đổi; useMemo cache result calculation; useCallback cache function identity. Đây là performance hints, không phải correctness contract: React có thể bỏ cache trong trường hợp được phép, nên logic phải vẫn đúng khi calculation chạy lại.
const visibleRows = useMemo(
() => filterAndSort(rows, filter, sort),
[rows, filter, sort]
);
const selectRow = useCallback(id => {
setSelectedId(id);
}, []);
const Row = memo(function Row({ row, onSelect }) {
return <button onClick={() => onSelect(row.id)}>{row.name}</button>;
});
memo; custom comparator đắt hoặc bỏ sót function closure có thể chậm hơn và tạo stale behavior. Chỉ thêm memo sau khi Profiler chỉ ra subtree/calculation đáng kể.4. List, code split và delivery budget
Stable key giữ identity khi insert/reorder nhưng không làm list lớn rẻ đi. Dùng windowing cho viewport dài, pagination cho dataset/product flow phù hợp, và đo overscan/accessibility. Không dùng index key khi item có thể đổi vị trí hoặc local row state cần bám entity.
Lazy-load theo route hoặc feature có ranh giới rõ; đặt Suspense fallback giữ layout ổn định. Prefetch/preload theo khả năng user sắp cần và budget mạng, không tải tất cả “cho nhanh”. Audit duplicate dependencies, third-party scripts, source maps và polyfills; cache asset bằng content hash.
5. React Compiler thay đổi gì?
React Compiler phân tích code tương thích và tự động áp dụng memoization để giảm manual useMemo, useCallback và memo trong nhiều trường hợp. Compiler dựa Rules of React — pure render, không mutate props/state và Hook usage hợp lệ. Nó không sửa state model rộng, network waterfall, huge DOM hoặc expensive third-party script.
Adopt dần với lint/diagnostics và production measurement. Compiler có thể skip component không chứng minh an toàn; không nên đổi behavior để ép compile. Existing manual memo có thể vẫn cần ở API identity contract hoặc hotspot được đo, nhưng phải xem hướng dẫn version đang dùng trước khi xóa hàng loạt.
6. Production profiling và regression gates
Development có Strict Mode, extra warnings và source transforms nên timing khác production. Đo optimized build trên hardware/network đại diện, profile flow đủ dài để tránh warm-up noise, và so sánh nhiều lần. `
Đặt performance budget cho route JS, image, LCP/INP/CLS hoặc critical interaction; theo dõi percentile field thay vì average. Mọi optimization cần regression test correctness, đặc biệt memo comparator, stale closure, virtualized keyboard navigation và hydration.