Part 07 · Performance · 7.1.09

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.

Optimization loop: chọn user flow và metric → ghi baseline trên production build/device đại diện → profile → sửa root cause nhỏ nhất → đo lại correctness và metric.

1. Chẩn đoán đúng tầng

Triệu chứngBằng chứng cần xemRoot cause thường gặp
Click phản hồi chậmBrowser Performance trace, INPLong task, render nặng, sync handler
Trang hiện chậmNetwork waterfall, LCPData chain, bundle, image/font
Scroll giậtMain-thread/layout/paint traceHuge list, forced layout, expensive style
Nhiều component renderReact DevTools ProfilerState/context quá cao, unstable props
Layout nhảyLayout shift track, CLSThiế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.

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>;
});
Memoization tax: một prop luôn mới phá toàn bộ 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, useCallbackmemo 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. `` có runtime overhead; production profiling bundle chỉ bật có chủ đích.

Đặ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.

Review checklist: có baseline; phân biệt React render với browser work; root cause được sửa trước cache; memo có evidence; list/bundle có budget; compiler adoption có diagnostics; production field metric xác nhận cải thiện.
Tài liệu: React Profiler · memo API · useMemo API · useCallback API · React Compiler · Web Vitals