jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Web Performance · Part 22 — Capstone 2: Systematic Performance Investigation

Ghép mọi phần chuyên sâu thành khung chẩn đoán triệu chứng → metric → công cụ → cách sửa, từ field data tới nguyên nhân gốc xuyên mọi tầng.

Phần 12 dạy quy trình audit + budget. Capstone thứ hai này dạy kỹ năng cao hơn: điều tra — khi field data báo một metric xấu, làm sao truy ngược tới đúng nguyên nhân giữa hàng chục khả năng, rồi chọn đúng cách sửa. Đây là điểm hội tụ của cả loạt bài chuyên sâu 13–21, đóng gói thành một khung quyết định lặp lại.

Khác audit (quét rộng tìm mọi vấn đề), điều tra là truy sâu một triệu chứng cụ thể tới root cause. Cả hai cần thiết; phần này về cái thứ hai.


1. Vòng lặp điều tra

① ĐO (field)      RUM/CrUX cho thấy metric nào xấu, ở đâu (route/thiết bị/mạng)
② PHÂN RÃ         dùng Attribution để chẻ metric thành các giai đoạn
③ TÁI HIỆN (lab)  reproduce trong DevTools với throttle giống phân khúc xấu
④ TÌM GỐC         dùng đúng công cụ cho giai đoạn nghi ngờ
⑤ SỬA 1 THỨ       đổi đúng một biến số
⑥ ĐO LẠI          xác nhận ở lab, rồi theo dõi field sau deploy
⑦ LẶP / chốt budget

Nguyên tắc xuyên suốt cả series: đo trước, sửa sau; field cho biết kết quả người dùng, lab giúp chẩn đoán cơ chế; sửa một thứ một lúc để biết cái gì có tác dụng. Field cũng có sampling bias/độ trễ, nên luôn đọc coverage và sample count.


2. Bản đồ triệu chứng → metric → công cụ → cách sửa

Đây là trái tim của capstone: khung tra cứu nối mọi phần.

LCP cao (nội dung chính hiện chậm)
  Đo:    LCP Attribution → TTFB? resource load delay/duration? element render delay?
  Công cụ: WebPageTest waterfall, Lighthouse, RUM Attribution
  Sửa:   TTFB → SSR/edge/cache (Part 15,19); load → discover ảnh LCP sớm trong HTML,
         dùng fetchpriority và chỉ preload khi resource bị phát hiện trễ (Part 14);
         render delay → giảm JS chặn, hydration (Part 15,16)

INP cao (bấm/gõ phản hồi chậm)
  Đo:    INP Attribution → inputDelay? processing? presentation?
  Công cụ: LoAF/Attribution khi browser hỗ trợ, Performance panel để tái hiện
  Sửa:   inputDelay → chia task + yield (Part 16); processing → tối ưu/worker (Part 16);
         presentation → giảm reflow/DOM (Part 17); third-party? (Part 20)

CLS cao (layout nhảy)
  Đo:    CLS Attribution → largestShiftTarget
  Công cụ: Performance panel (Layout Shift regions), DevTools
  Sửa:   đặt kích thước ảnh/embed, reserve space, tránh chèn trên (Part 7);
         font swap (Part 10); streaming cần đặt chỗ trước (Part 15)

TTFB cao (server chậm trả byte đầu)
  Công cụ: Server-Timing, Navigation/Resource Timing, WebPageTest
  Sửa:   cache/CDN/edge (Part 19), SSG/ISR (Part 15), tối ưu backend/query

Bundle phình / tải chậm
  Công cụ: treemap, size-limit (Part 21)
  Sửa:   code-split, tree-shake, thay dep nặng, lazy (Part 8,21)

App chậm dần theo thời gian
  Công cụ: heap snapshot, Performance memory (Part 18)
  Sửa:   gỡ listener/timer, fix detached DOM (Part 18)

3. Tái hiện đúng điều kiện

Lỗi field thường không tái hiện trên MacBook cắm điện. Phải mô phỏng phân khúc xấu (từ bước ② phân khúc RUM):

DevTools cài đặt tái hiện:
  - CPU throttling được hiệu chỉnh theo máy chạy; 4x–6x chỉ là điểm bắt đầu
  - Network: Slow 4G
  - cache: disabled (first visit) hoặc enabled (repeat) tùy kịch bản đo
  - device emulation đúng viewport
  - thử cả cold start và sau nhiều tương tác (cho INP/memory)

Nếu field nói “mobile p75 INP = 600ms” mà lab không tái hiện, có thể throttle chưa sát, user flow khác, thiết bị/memory khác, third-party/A-B test khác hoặc sample field gồm trạng thái app bạn chưa dựng lại. Ưu tiên test trên thiết bị đại diện; throttle desktop chỉ là mô hình, không phải bản sao điện thoại.


4. Một ca điều tra mẫu (end-to-end)

Triệu chứng:  Search Console báo INP "Poor" trên route /products (mobile)
① ĐO:         RUM cho thấy INP p75 = 550ms, chỉ mobile, chỉ /products
② PHÂN RÃ:    Attribution → processingDuration chiếm 400ms; target = nút "Add filter"
③ TÁI HIỆN:   CPU throttle đã hiệu chỉnh (~4x ở máy test) + Slow 4G → click filter mất ~500ms
④ TÌM GỐC:    LoAF → script app.js, hàm applyFilters() chạy 380ms (lọc + re-render cả list)
⑤ SỬA:        chia applyFilters thành chunk + scheduler.yield (Part 16);
              thêm content-visibility cho list item (Part 17)
⑥ ĐO LẠI:     lab → click ~120ms; deploy → field p75 INP /products mobile xuống 180ms ✅
⑦ CHỐT:       thêm RUM alert/budget INP cho route + lấy mẫu LoAF diagnostic (Part 21)

Lưu ý cách điều tra đi thẳng tới nguyên nhân nhờ phân rã + công cụ đúng, thay vì đoán mò “chắc do bundle to”.


5. Các bẫy điều tra thường gặp

❌ Tối ưu cái dễ đo thay vì cái quan trọng (lab score thay vì field INP)
❌ Sửa nhiều thứ cùng lúc → không biết cái nào có tác dụng
❌ Tin "trực giác" về bottleneck thay vì đo (thường sai)
❌ Bỏ qua đuôi (p95/p99) — một nhóm nhỏ khổ sở vẫn là vấn đề
❌ Coi một mức throttle trên máy dev là bản sao mọi thiết bị thật
❌ Sửa xong không theo dõi field → hồi quy âm thầm quay lại

6. Toàn series — bản đồ Web Performance

NỀN TẢNG (1–12)
  1  Tư duy & RAIL          7  Tối ưu CLS
  2  Core Web Vitals        8  JS performance & bundle
  3  Công cụ đo             9  Ảnh & media
  4  Critical rendering path 10 Fonts
  5  Tối ưu LCP            11  Network & caching
  6  Tối ưu INP            12  Capstone 1 — audit & budget

CHUYÊN SÂU (13–22)
  13 RUM & field data       18 Memory & phiên dài
  14 Resource hints/Early Hints 19 Network protocol (HTTP/3)
  15 Rendering & delivery    20 Third-party scripts
  16 INP & scheduling (LoAF) 21 Budgets & culture at scale
  17 Rendering pipeline/CSS  22 Capstone 2 — điều tra (bài này)

7. Tóm tắt

  • Điều tra = truy sâu một triệu chứng tới root cause; vòng lặp: đo field kèm coverage/sample count → phân rã → tái hiện lab/thiết bị thật → tìm gốc → sửa một thứ → đo lại → chốt budget.
  • Dùng bản đồ triệu chứng → metric → công cụ → cách sửa để đi thẳng tới nguyên nhân thay vì đoán: mỗi Core Web Vital có giai đoạn phân rã và bộ công cụ riêng.
  • Tái hiện đúng điều kiện (thiết bị đại diện, throttle đã hiệu chỉnh, cold/warm, đúng user flow/variant) — lỗi field hiếm khi hiện nguyên dạng trên máy dev mạnh.
  • Tránh bẫy: tối ưu cái dễ đo thay vì cái quan trọng, sửa nhiều thứ cùng lúc, tin trực giác, bỏ đuôi p95/p99, không theo dõi field sau sửa.
  • Đây là điểm hội tụ của cả series: biến hiệu năng từ đoán mò thành chẩn đoán có hệ thống, neo vào field data và đóng vòng bằng budget + monitoring.

Cảm ơn bạn đã đi hết hành trình Web Performance & Core Web Vitals. Từ RAIL ở Phần 1 tới khung điều tra ở đây, thông điệp không đổi: đo trước, sửa cái lớn nhất, xác nhận bằng field data, và đặt guardrails để thành quả không trôi.