Web Performance · Part 14 — Resource Hints, Priorities & Early Hints
Rút ngắn đường tới byte quan trọng: preconnect/dns-prefetch, preload/modulepreload/prefetch, fetchpriority & Priority Hints, 103 Early Hints, và Speculation Rules cho prefetch/prerender.
Phần 4 vẽ critical rendering path. Phần này về các công cụ điều khiển trình tự và độ ưu tiên tải — vũ khí trực tiếp nhất cho LCP và TTFB. Trình duyệt có scheduler tải riêng, nhưng nó đoán; resource hints là cách bạn nói cho nó biết cái gì quan trọng, sớm hơn nó tự khám phá.
Tư duy nền: mỗi tài nguyên quan trọng được phát hiện trễ một vòng (parse HTML → thấy CSS → thấy font trong CSS…) là một round-trip mạng bị lãng phí. Hints rút ngắn chuỗi khám phá đó.
1. preconnect & dns-prefetch — ấm kết nối sớm
Kết nối tới một origin mới có thể tốn DNS + thiết lập transport + TLS; số round-trip thực tế phụ thuộc cache DNS, connection reuse và TCP hay QUIC. Nếu bạn biết sẽ cần một origin (CDN ảnh, API, font host), preconnect yêu cầu trình duyệt chuẩn bị kết nối sớm.
<!-- Ấm sẵn kết nối tới origin quan trọng (dùng cho thứ chắc chắn cần sớm) -->
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
<!-- dns-prefetch: chỉ phân giải DNS — rẻ hơn, dùng cho origin "có thể cần" -->
<link rel="dns-prefetch" href="https://analytics.example.com">
Với tài nguyên được fetch ở CORS mode như font,
crossorigingiúp kết nối preconnect khớp credential mode của request thật; thiếu nó có thể khiến kết nối không được tái dùng. Chỉ preconnect vài origin chắc chắn cần sớm — kết nối mở sẵn vẫn tốn socket, CPU và pin.
2. preload — tải sớm tài nguyên quan trọng bị phát hiện trễ
preload khai báo để trình duyệt phát hiện và bắt đầu tải tài nguyên sớm, kể cả khi nó được tham chiếu sâu (font trong CSS, ảnh LCP trong JS). Mức ưu tiên còn phụ thuộc loại tài nguyên, as, heuristic của browser và fetchpriority; preload không đồng nghĩa mọi request đều ở mức cao nhất.
<!-- Font dùng cho text trên màn hình đầu — nếu không, bị phát hiện sau khi CSS tải xong -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<!-- Ảnh LCP đặt qua CSS background hoặc JS (trình duyệt không tự thấy sớm) -->
<link rel="preload" href="/hero.avif" as="image" fetchpriority="high">
Quy tắc dùng preload: chỉ cho tài nguyên quan trọng cho màn hình đầu mà trình duyệt phát hiện trễ. Preload thứ trình duyệt vốn tìm thấy sớm (như <img src> trong HTML) là thừa và có thể phản tác dụng (cạnh tranh băng thông).
3. modulepreload & prefetch
<!-- modulepreload: tải, parse/compile sẵn module; engine có thể lấy cả dependency graph -->
<link rel="modulepreload" href="/app.js">
<!-- prefetch: tải tài nguyên cho điều hướng TƯƠNG LAI, ưu tiên THẤP, vào cache -->
<link rel="prefetch" href="/next-page-data.json">
Phân biệt rõ:
| Hint | Cho | Ưu tiên | Khi nào |
|---|---|---|---|
preload | trang hiện tại | theo loại tài nguyên/hint | tài nguyên màn hình đầu bị phát hiện trễ |
modulepreload | trang hiện tại | cao | ES module quan trọng |
prefetch | điều hướng tương lai | thấp (idle) | trang/asset người dùng có thể tới |
prefetch thường có ưu tiên thấp và browser có thể trì hoãn, bỏ qua hoặc loại khỏi cache. Nó vẫn dùng dữ liệu và có thể cạnh tranh băng thông, nên chỉ đầu cơ khi xác suất dùng cao và tôn trọng tín hiệu tiết kiệm dữ liệu.
4. fetchpriority & Priority Hints
Trình duyệt gán độ ưu tiên mặc định cho mỗi tải (CSS render-blocking thường cao, ảnh được điều chỉnh theo khả năng hiển thị…). fetchpriority cho bạn gửi một hint tương đối; browser vẫn có quyền cân bằng scheduler.
<!-- Nâng ứng viên LCP khi heuristic mặc định chưa ưu tiên đủ sớm -->
<img src="/hero.avif" fetchpriority="high" alt="...">
<!-- Hạ ảnh dưới màn hình / không quan trọng -->
<img src="/footer-logo.png" fetchpriority="low" loading="lazy" alt="...">
<!-- Hạ ưu tiên một fetch không gấp trên browser hỗ trợ -->
<script>fetch('/non-critical.json', { priority: 'low' });</script>
Ảnh LCP được khai báo sớm trong HTML vẫn có thể khởi đầu ở priority thấp hơn CSS/font quan trọng. fetchpriority="high" giúp browser ưu tiên đúng ứng viên LCP, nhưng chỉ nên đặt trên một vài tài nguyên thật sự quan trọng và phải đo lại waterfall.
5. 103 Early Hints — dùng thời gian “chết” của server
Khi server cần thời gian sinh HTML (truy vấn DB, render), trình duyệt ngồi chờ TTFB. HTTP 103 Early Hints cho server gửi trước các Link: preload/preconnect trong khi vẫn đang xử lý response chính.
Không có Early Hints: Có 103 Early Hints:
request → request →
[server xử lý 400ms...] ← 103 Early Hints (preload CSS/font)
← 200 HTML [trình duyệt BẮT ĐẦU tải CSS/font]
→ mới tải CSS/font [server xử lý 400ms...]
← 200 HTML (CSS/font đã sẵn)
HTTP/1.1 103 Early Hints
Link: </styles.css>; rel=preload; as=style
Link: <https://cdn.example.com>; rel=preconnect
HTTP/1.1 200 OK
...
Early Hints cần hỗ trợ từ CDN/server và mức hỗ trợ preload khác nhau giữa browser (preconnect rộng hơn). Nó chỉ đáng giá khi response cuối có server think-time đủ lớn; site tĩnh trả 200 ngay thường không hưởng lợi. Chỉ hint URL ổn định, cacheable và lặp lại Link cần thiết trong response cuối để tránh tải thừa hoặc cache miss.
6. Speculation Rules — prefetch & prerender điều hướng kế
Speculation Rules là API mạnh hơn <link rel=prefetch> cho điều hướng: prefetch tài liệu hoặc prerender cả trang theo rule. Tuy vậy, đây chưa phải baseline đa engine; cần feature-detect và giữ trải nghiệm đúng khi browser bỏ qua rules.
<script type="speculationrules">
{
"prefetch": [{ "where": { "href_matches": "/*" }, "eagerness": "moderate" }],
"prerender": [{ "where": { "selector_matches": "a.product-link" }, "eagerness": "conservative" }]
}
</script>
prefetch: tải tài liệu HTML trước → nhẹ hơn prerender nhưng vẫn tốn dữ liệu/cache
prerender: dựng CẢ trang (chạy JS, render) trong nền → vào gần như tức thì (tốn tài nguyên)
eagerness: conservative | moderate | eager | immediate (cân tốc độ vs lãng phí)
Cẩn thận prerender với trang có side-effect (analytics): kiểm tra
document.prerenderingvà hoãn tớiprerenderingchange(đã bàn ở góc nhìn trình duyệt). Đo bằng RUM (Part 13) xem hit-rate prefetch có đáng chi phí không.
Ưu tiên URL same-origin. Cross-origin speculation có giới hạn credential/opt-in và privacy riêng; đừng coi nó như một fetch bình thường mang đầy đủ cookie. moderate/conservative thường là điểm bắt đầu an toàn hơn immediate cho document rules rộng.
7. Tóm tắt
preconnectấm sẵn DNS+TCP+TLS cho origin quan trọng (kèmcrossorigincho font);dns-prefetchrẻ hơn cho origin “có thể cần”. Đừng lạm dụng.preloadchỉ cho tài nguyên màn hình đầu bị phát hiện trễ (font, ảnh LCP qua CSS/JS);modulepreloadcho ES module;prefetchcho tương lai nhưng vẫn có chi phí dữ liệu.fetchpriority="high"trên ảnh LCP là một trong các tinh chỉnh LCP hiệu quả nhất; hạlowcho tài nguyên phụ.- 103 Early Hints tận dụng server think-time bằng preload/preconnect sớm; chỉ hint tài nguyên cacheable, ổn định và kiểm tra hỗ trợ browser/CDN.
- Speculation Rules prefetch/prerender điều hướng kế trên browser hỗ trợ; feature-detect, chỉnh
eagerness, coi chừng side-effect/cross-origin và đo hit-rate bằng RUM.
Phần tiếp theo: Rendering & delivery strategies — CSR/SSR/SSG/ISR/streaming và islands/partial/progressive hydration ảnh hưởng LCP/INP/CLS/TTFB ra sao, và chọn kiến trúc nào cho mục tiêu nào.