Web Performance · Part 3 — Measurement Tools: Lighthouse, DevTools, CrUX & RUM
Measure right before you fix right. Lighthouse and the Performance tab for diagnosis (lab), CrUX and self-built RUM for real users (field), plus how to throttle to match typical hardware.
Phần 1 nói “đo trước, sửa sau”, Phần 2 nói “đo cái gì”. Phần này nói “đo bằng gì”. Mỗi công cụ trả lời một câu hỏi khác nhau — dùng sai công cụ dẫn tới kết luận sai. Ta chia theo trục lab (chẩn đoán) và field (sự thật).
1. Lighthouse — điểm khởi đầu (lab)
Lighthouse (trong DevTools, tab Lighthouse, hoặc npx lighthouse) chạy một bài kiểm tra mô phỏng và cho điểm 0–100 cùng danh sách gợi ý. Đây là cách nhanh nhất để có cái nhìn tổng quan.
# Run Lighthouse from CLI, export JSON report for comparison/CI
npx lighthouse https://example.com --output=json --output-path=./report.json \
--only-categories=performance --throttling-method=simulate
Hiểu đúng về Lighthouse: nó là lab data — chạy trên một cấu hình mô phỏng cố định. Cực hợp để chẩn đoán (“gợi ý nào đáng làm”) và theo dõi hồi quy trong CI, nhưng điểm số không phải trải nghiệm người dùng thật. Đừng bị ám ảnh kéo điểm lên 100; hãy nhìn các cơ hội (opportunities) cụ thể nó liệt kê.
Lighthouse cũng cho TBT thay cho INP (navigation audit không có chuỗi tương tác thật) và CLS trong cửa sổ audit. Đây là tín hiệu lab hữu ích, không thay được field data trong toàn bộ lượt truy cập.
2. Tab Performance — chẩn đoán sâu (lab)
Khi Lighthouse nói “có long task” hay “LCP chậm” nhưng không rõ vì sao, tab Performance của DevTools cho bạn dòng thời gian chi tiết: từng task JS, layout, paint, network.
Quy trình profile chuẩn:
- Mở tab Performance, chọn CPU/network throttling đại diện cho đối tượng của bạn; giữ cùng preset khi so sánh trước/sau. Nếu có thể, hiệu chỉnh preset bằng field data thay vì mặc định 4×/Slow 4G cho mọi site.
- Bấm Record, tải lại trang hoặc thực hiện tương tác cần đo, dừng record.
- Đọc các track chính:
- Main thread: task trên 50ms thường có cờ đỏ; mở call tree để tìm đoạn chặn input/TBT.
- Mốc LCP/FCP: cho biết nội dung được vẽ lúc nào và phần tử LCP nào được chọn.
- Layout Shifts: chọn từng shift để xem phần tử bị dịch chuyển và nguyên nhân gần đó.
Mẹo: dùng
performance.mark()/performance.measure()(Phần 1) để gắn nhãn đoạn code của bạn — chúng hiện ngay trên timeline, giúp định vị code của mình giữa rừng task của trình duyệt.
3. CrUX — sự thật từ người dùng Chrome (field)
Chrome User Experience Report (CrUX) là dữ liệu field tổng hợp từ một tập người dùng Chrome đủ điều kiện và đã bật đồng bộ/thống kê sử dụng. Dữ liệu này cấp nguồn cho PageSpeed Insights, Search Console và nhiều bề mặt CWV của Google; Core Web Vitals là một trong nhiều tín hiệu trải nghiệm trang của Google Search.
Cách truy cập:
- PageSpeed Insights (pagespeed.web.dev): nhập URL → thấy CrUX (field) và Lighthouse (lab). Kiểm tra nhãn kỹ vì PSI có thể hiển thị dữ liệu cấp URL hoặc fallback về origin khi URL thiếu mẫu.
- CrUX API / BigQuery: lấy dữ liệu theo chương trình cho dashboard.
- Search Console: báo cáo Core Web Vitals theo nhóm URL.
Hạn chế: CrUX chỉ có với URL/origin đủ điều kiện và đủ mẫu, dùng cửa sổ cuộn 28 ngày nên phản ánh deploy mới khá chậm, và không đại diện cho mọi trình duyệt/người dùng. Để có dữ liệu sớm hơn và của riêng bạn, cần RUM.
4. RUM — đo người dùng thật của riêng bạn (field)
Real User Monitoring (RUM) là tự thu chỉ số từ chính người dùng của bạn. Ưu điểm so với CrUX: dữ liệu tới sớm hơn và cắt lát được theo thiết bị/quốc gia/route/phiên bản. Tuy nhiên, độ phủ vẫn phụ thuộc API trình duyệt: chẳng hạn CLS qua web-vitals hiện chủ yếu đo được trên Chromium. Dựng RUM tối giản với web-vitals (Phần 2):
import { onLCP, onINP, onCLS, onTTFB, onFCP } from 'web-vitals';
interface VitalPayload {
name: string;
value: number;
rating: string;
id: string;
path: string;
conn?: string; // connection type, for slicing by network
}
function report(metric: { name: string; value: number; rating: string; id: string }) {
const payload: VitalPayload = {
...metric,
path: location.pathname,
conn: (navigator as Navigator & { connection?: { effectiveType?: string } }).connection
?.effectiveType,
};
const body = JSON.stringify(payload);
if (!navigator.sendBeacon?.('/rum', body)) {
void fetch('/rum', { method: 'POST', body, keepalive: true });
}
}
onLCP(report);
onINP(report);
onCLS(report);
onTTFB(report);
onFCP(report);
Phía server upsert theo metric.id, rồi tính p75 theo route và loại thiết bị để biết trang nào đang tệ với người dùng thật. Đây là vòng lặp phản hồi quan trọng nhất: deploy → đo field → thấy chỗ tệ → sửa → đo lại.
Quan trọng: tính p75 để so với ngưỡng CWV, đồng thời theo dõi p95 để thấy phần đuôi. Chỉ gửi route đã chuẩn hóa và metadata thật sự cần; không thu query string, định danh hay dữ liệu nhạy cảm ngoài mục đích đo đã công bố.
5. WebPageTest — phân tích chuyên sâu (lab nâng cao)
webpagetest.org cho chọn nhiều agent, thiết bị, cấu hình mạng và vị trí địa lý; kết quả có waterfall chi tiết từng request, filmstrip (chuỗi ảnh chụp quá trình tải), và so sánh nhiều URL cạnh nhau. Khi cần hiểu thứ tự tải tài nguyên và điều gì chặn điều gì, đây là công cụ rất mạnh.
Dùng filmstrip để thấy chính xác khoảnh khắc LCP hiện, và waterfall để phát hiện request nào đến muộn/chặn render (dẫn vào Phần 4 về critical rendering path).
6. Chọn công cụ theo câu hỏi
| Câu hỏi của bạn | Công cụ |
|---|---|
| Trang tôi nhanh với người dùng thật không? | CrUX / RUM (field) |
| Trang nào/route nào đang tệ? | RUM (slice by path) |
| Vì sao nó chậm? (chẩn đoán) | Performance tab, WebPageTest |
| Có cơ hội tối ưu nào dễ? | Lighthouse |
| Có bị hồi quy sau deploy không? | Lighthouse CI + RUM alert |
Nguyên tắc: field data quyết định có vấn đề không và ở đâu; lab data giúp hiểu vì sao và sửa thế nào. Cả hai bổ trợ, không thay thế nhau.
Tóm tắt
- Lighthouse (lab): tổng quan + cơ hội tối ưu + CI; đừng ám ảnh điểm 100, nhìn opportunities.
- Tab Performance (lab): chẩn đoán sâu long task/LCP/CLS; dùng cấu hình throttle đại diện và nhất quán.
- CrUX (field): dữ liệu tổng hợp từ người dùng Chrome đủ điều kiện, cấp nguồn cho nhiều công cụ CWV; xem nhanh qua PageSpeed Insights.
- RUM tự dựng (field): dữ liệu sớm, cắt lát theo route/thiết bị; tính p75 + p95, dùng
sendBeaconvới fallback và tôn trọng giới hạn API/quyền riêng tư. - WebPageTest: waterfall + filmstrip cho phân tích thứ tự tải.
Phần tiếp theo: Critical rendering path — hành trình từ HTML tới pixel, và những gì chặn render.