Web Performance

Preload, prefetch và preconnect: khi nào từng loại thực sự hữu ích

Gợi ý tài nguyên hữu ích khi chúng khớp với các nút thắt thực tế của trình duyệt. Dùng một cách mù quáng, chúng tạo thêm nhiễu về mức ưu tiên và đôi khi làm trang chậm hơn.

The Wux Webtools Team The Wux Webtools Team 20 phút đọc Hỗ trợ AI, được con người xem xét
A simplified browser loading waterfall showing early resource hints for a web page.
Mục lục
  1. Gợi ý tài nguyên không phải phép màu
  2. Trình duyệt vốn đã làm tốt điều gì
  3. Preload: cho tài nguyên của trang hiện tại bị phát hiện quá muộn
  4. Preload và hình ảnh LCP
  5. Prefetch: cho trang kế tiếp, không phải trang này
  6. Preconnect: cho các kết nối tốn kém tới origin quan trọng
  7. DNS-prefetch: người anh em nhẹ hơn
  8. Cách quyết định: một workflow thực tế
  9. 1. Xác định nút thắt
  10. 2. Thêm từng gợi ý một
  11. 3. Kiểm tra tác dụng phụ về mức ưu tiên
  12. 4. Xác minh headers và caching
  13. Những lỗi thường gặp
  14. Preload quá nhiều
  15. Dùng prefetch cho tài nguyên bắt buộc
  16. Preconnect tới mọi bên thứ ba
  17. Quên điều kiện di động
  18. Một bảng quyết định đơn giản
  19. Quy tắc bình tĩnh

Gợi ý tài nguyên không phải phép màu

preload, prefetch, và preconnect thường được xem như một checklist hiệu năng. Thêm vài thẻ vào <head>, chạy lại Lighthouse, rồi cảm thấy yên tâm hơn. Chúng không hoạt động như vậy.

Những gợi ý này là chỉ thị cho pipeline tải của trình duyệt. Chúng có thể giúp ích khi bạn biết một điều mà trình duyệt không thể phát hiện đủ sớm. Chúng có thể gây hại khi bạn đoán mò, ưu tiên quá mức cho công việc không quan trọng, hoặc khởi động sẵn các kết nối mà người dùng sẽ không bao giờ cần.

Phiên bản ngắn gọn:

  • Dùng preload cho các tài nguyên cần thiết cho trang hiện tại, nhưng bị phát hiện quá muộn.
  • Dùng prefetch cho các tài nguyên có khả năng cần trong lần điều hướng tương lai, không phải các thành phần thiết yếu của trang hiện tại.
  • Dùng preconnect cho các origin bên thứ ba quan trọng, nơi việc thiết lập kết nối là một độ trễ thực sự.

Câu hỏi thực tế không phải là “gợi ý nào nhanh nhất?” Mà là “trình duyệt đang chờ điều gì, và gợi ý này có thể loại bỏ sự chờ đợi đó không?”

Trình duyệt vốn đã làm tốt điều gì

Các trình duyệt hiện đại không phải là những công cụ tải tệp thụ động. Chúng phân tích HTML, quét trước để tìm tài nguyên, gán mức ưu tiên, tái sử dụng kết nối, trì hoãn công việc chưa hiển thị, và thích ứng với điều kiện mạng.

Điều đó nghĩa là gợi ý tài nguyên nên được dùng có chọn lọc. Nếu một stylesheet, script, hình ảnh, hoặc font đã được phát hiện sớm và được gán đúng mức ưu tiên, việc thêm gợi ý có thể chẳng làm gì. Tệ hơn, nó có thể cạnh tranh với những tài nguyên quan trọng hơn.

Trước khi thêm gợi ý, hãy xem waterfall trace trong DevTools hoặc một báo cáo lab. Nếu bạn dùng Lighthouse, hãy bắt đầu từ phần diagnostics thay vì điểm số; chúng tôi có một hướng dẫn riêng về cách đọc báo cáo Lighthouse mà không hoảng — nhưng lưu ý URL chính xác có phân biệt chữ hoa chữ thường, vì vậy hãy dùng bài viết được liên kết từ phần điều hướng trên site của bạn nếu cần.

Bằng chứng thực tế thường hiện rõ ở ba nơi:

  1. Một tài nguyên quan trọng bắt đầu muộn vì trình duyệt phát hiện nó muộn.
  2. Một kết nối tới origin quan trọng mất thời gian đáng kể trước request đầu tiên.
  3. Một tài nguyên của trang kế tiếp có khả năng dự đoán cao và rẻ để tải trong thời gian rảnh.

Nếu không điều nào trong số đó đúng, gợi ý có lẽ chỉ là trang trí.

Preload: cho tài nguyên của trang hiện tại bị phát hiện quá muộn

preload nói với trình duyệt: “Hãy tải tài nguyên này ngay vì trang hiện tại sẽ cần nó.”

Một ví dụ điển hình là web font được tham chiếu bên trong CSS. Trình duyệt phải tải HTML, phát hiện CSS, tải CSS, phân tích nó, phát hiện font, rồi mới request font. Nếu font đó quan trọng cho văn bản above-the-fold, việc phát hiện có thể đủ muộn để gây layout shifts hoặc trì hoãn việc render văn bản.

Một preload có thể đưa request đó lên sớm hơn:

<link rel='preload' href='/fonts/inter-var.woff2' as='font' type='font/woff2' crossorigin>

Thuộc tính as rất quan trọng. Nó cho trình duyệt biết đây là loại tài nguyên gì, điều này ảnh hưởng đến mức ưu tiên, caching, content security policy, và request headers. Font cũng thường cần crossorigin, ngay cả khi được phục vụ từ cùng một site, vì việc tải font dùng chế độ CORS.

Các ứng viên preload tốt gồm:

  • Web font chính dùng cho văn bản hiển thị.
  • Hero image là phần tử Largest Contentful Paint và không thể được phát hiện sớm.
  • Một tệp CSS quan trọng được tải gián tiếp.
  • Một module hoặc script cần rất sớm, nhưng bị ẩn sau một script khác.

Các ứng viên preload không tốt gồm:

  • Mọi độ đậm font trong design system.
  • Hình ảnh below the fold.
  • Script không cần cho lần render ban đầu.
  • Tài nguyên mà trình duyệt đã phát hiện trong chunk HTML đầu tiên.

Preload mạnh vì nó ảnh hưởng đến mức ưu tiên của trang hiện tại. Đó cũng là lý do nó dễ bị dùng sai. Nếu bạn preload năm asset lớn, bạn không còn đang giúp trình duyệt nữa. Bạn đang tranh luận với nó.

Font là trường hợp kinh điển. Preload một tệp font chính có thể hữu ích. Preload sáu độ đậm và italic thường làm mọi thứ tệ hơn. Nếu font là nút thắt của bạn, hãy sửa bộ font trước; hướng dẫn của chúng tôi về lý do web fonts are still the easiest performance win on most sites trình bày chi tiết hơn về việc dọn dẹp đó.

Preload và hình ảnh LCP

Preload một hình ảnh LCP có thể hữu ích khi hình ảnh không hiện diện trong HTML ban đầu. Các nguyên nhân phổ biến gồm hình nền CSS, component render phía client, hoặc logic hình ảnh responsive xuất hiện muộn.

Nhưng nếu hero image của bạn đã nằm trong HTML dưới dạng một <img> với srcset, sizes, kích thước hợp lý, và không lazy loading, trình duyệt có lẽ có thể tìm thấy nó nhanh chóng. Trong trường hợp đó, thêm fetchpriority='high' có thể phù hợp hơn preload, tùy vào trang.

Một bài kiểm tra tốt: nếu request hình ảnh bắt đầu muộn trong waterfall và trở thành phần tử LCP, hãy cân nhắc preload. Nếu nó bắt đầu sớm nhưng tải xuống chậm, vấn đề là kích thước, định dạng, hành vi CDN, hoặc độ trễ server — không phải việc phát hiện. Về quyết định định dạng hình ảnh, xem when AVIF beats WebP and when it does not.

Prefetch: cho trang kế tiếp, không phải trang này

prefetch nói với trình duyệt: “Tài nguyên này có thể sớm cần, nhưng hiện tại chưa bắt buộc.”

Sự phân biệt đó rất quan trọng. Prefetch được chủ ý đặt ở mức ưu tiên thấp. Trình duyệt có thể tải nó trong thời gian rảnh và lưu lại để dùng sau. Trình duyệt cũng có thể bỏ qua nó trên kết nối kém, chế độ tiết kiệm dữ liệu, hoặc khi chịu áp lực bộ nhớ.

Dùng prefetch khi ý định của người dùng đủ rõ để khiến tài nguyên kế tiếp có khả năng cao sẽ cần.

Các ứng viên prefetch tốt gồm:

  • Bước kế tiếp trong quy trình checkout nhiều trang.
  • Kết quả tìm kiếm sau khi người dùng bắt đầu nhập truy vấn, nếu route kế tiếp có thể dự đoán.
  • Các trang tài liệu được liên kết từ mục lục khi người dùng đang chủ động đọc nội dung gần đó.
  • Route chunks trong một single-page app sau khi người dùng hover hoặc focus một mục điều hướng.

Các ứng viên prefetch không tốt gồm:

  • Toàn bộ cây điều hướng của bạn.
  • Video lớn hoặc thư viện hình ảnh.
  • Script bên thứ ba “phòng khi cần”.
  • Các trang mà người dùng hiếm khi truy cập tiếp theo.

Prefetch là nơi sự tiết chế đem lại hiệu quả. Một tài nguyên được tải rồi không bao giờ dùng không phải là miễn phí. Nó tiêu tốn băng thông, năng lực server, năng lượng, và có thể cả dữ liệu của người dùng. Trên mạng di động, tải dự đoán có thể thực sự thiếu thân thiện.

Với nhiều site, chiến lược prefetch tốt nhất là dựa trên ý định. Đừng prefetch trang pricing ngay khi home page tải xong. Hãy prefetch nó khi người dùng mở menu pricing, hover liên kết pricing, hoặc cuộn gần một call-to-action dự đoán mạnh việc điều hướng.

Cũng hãy nhớ rằng hành vi trình duyệt khác nhau. Một số trình duyệt thận trọng với prefetch; một số thiết lập quyền riêng tư giảm hoặc tắt speculative loading. Hãy xem prefetch như một cải thiện cơ hội, không phải một cơ chế đảm bảo tính đúng đắn.

Preconnect: cho các kết nối tốn kém tới origin quan trọng

preconnect nói với trình duyệt: “Hãy bắt đầu thiết lập kết nối tới origin này ngay.”

Điều đó có thể bao gồm DNS lookup, TCP connection, và TLS negotiation. Với origin bên thứ ba, quá trình thiết lập này có thể mất hàng trăm mili giây, đặc biệt trên mạng có độ trễ cao. Nếu trang sắp cần một request quan trọng từ origin đó, preconnect có thể làm request về sau nhanh hơn.

Ví dụ:

<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>

Các ứng viên preconnect tốt gồm:

  • Một origin font dùng cho văn bản chặn render.
  • Một origin API quan trọng cần trong tương tác ban đầu.
  • Một origin CDN phục vụ asset above-the-fold.
  • Một nhà cung cấp thanh toán hoặc định danh cần ngay sau hành động của người dùng.

Các ứng viên preconnect không tốt gồm:

  • Endpoint analytics và quảng cáo không quan trọng với người dùng.
  • Origin chỉ được dùng trong một số phiên.
  • Danh sách dài các bên thứ ba.
  • Tài nguyên cùng origin, nơi trình duyệt đã có hoặc sẽ sớm mở kết nối.

Preconnect có chi phí duy trì. Socket mở tiêu tốn bộ nhớ và tài nguyên mạng. Trình duyệt sẽ đóng các kết nối không dùng, nhưng điều đó không khiến những preconnect không cần thiết trở nên vô hại.

Một quy tắc hữu ích: preconnect tối đa một hoặc hai origin bên thứ ba có độ tin cậy cao trên một trang. Nếu bạn thấy muốn thêm nhiều hơn, kiến trúc bên thứ ba của bạn có lẽ cần được rà soát hơn là các gợi ý cần được mở rộng.

DNS-prefetch: người anh em nhẹ hơn

Bạn cũng có thể thấy dns-prefetch:

<link rel='dns-prefetch' href='https://example-cdn.com'>

Cơ chế này chỉ phân giải tên miền. Nó không mở kết nối TCP hoặc TLS. Nó rẻ hơn preconnect, nhưng cũng ít hữu ích hơn.

DNS-prefetch có thể hợp lý cho các origin bên thứ ba có độ tin cậy thấp hơn, nơi full preconnect có vẻ quá mạnh tay. Trong thực tế, nếu một origin là quan trọng và chắc chắn sẽ sớm được dùng, hãy ưu tiên preconnect. Nếu nó chỉ có khả năng xảy ra, hãy dùng DNS-prefetch hoặc không làm gì.

Cách quyết định: một workflow thực tế

Bắt đầu bằng đo lường, không phải bằng thẻ.

1. Xác định nút thắt

Mở một performance trace và tìm việc phát hiện muộn. Request font, hero image, hoặc script có chỉ bắt đầu sau khi một tệp khác đã được tải xuống và phân tích không? Đó là ứng viên preload.

Nếu một request chỉ bắt đầu sau một quá trình DNS/TCP/TLS dài tới origin bên thứ ba, đó là ứng viên preconnect.

Nếu trang hiện tại ổn nhưng lần điều hướng kế tiếp chậm một cách có thể dự đoán, prefetch có thể hữu ích.

2. Thêm từng gợi ý một

Gợi ý tài nguyên tương tác với nhau. Thêm một gợi ý, kiểm thử nó, và chỉ giữ lại nếu waterfall cải thiện và các chỉ số hướng tới người dùng không bị thụt lùi.

Với preload, hãy theo dõi xem tài nguyên được gợi ý có thực sự được dùng sớm không. Chrome có thể cảnh báo khi một tài nguyên preload không được dùng ngay sau khi tải. Hãy xem cảnh báo đó một cách nghiêm túc.

3. Kiểm tra tác dụng phụ về mức ưu tiên

Một preload có thể kéo băng thông khỏi CSS, JavaScript, hoặc hình ảnh quan trọng hơn. Một preconnect có thể chiếm một connection slot. Một prefetch có thể thêm lưu lượng nền.

Kết quả đúng không phải là “tệp được gợi ý bắt đầu sớm hơn.” Kết quả đúng là “trang trở nên tốt hơn một cách có ý nghĩa cho người dùng.” Hãy xem LCP, INP, CLS, và real-user monitoring khi có thể.

4. Xác minh headers và caching

Gợi ý có thể được gửi trong HTML hoặc HTTP Link headers. Headers hữu ích khi server biết sớm trang sẽ cần gì, nhưng chúng khó kiểm tra tùy tiện hơn. Nếu bạn đang debug xem một gợi ý có thực sự hiện diện trong production hay không, raw headers rất quan trọng; đây chính là tình huống được đề cập trong our guide to debugging redirects and HTTP headers.

Caching cũng quan trọng. Preload một tài nguyên với credentials không khớp, as sai, hoặc tham số URL khác có thể gây tải trùng lặp. Đó là một trong những cách phổ biến nhất khiến một preload có ý tốt trở thành lỗi hiệu năng.

Những lỗi thường gặp

Preload quá nhiều

Nếu mọi thứ đều quan trọng, thì chẳng có gì quan trọng. Hãy giới hạn preload ở các tài nguyên cần cho render ban đầu hoặc khả năng tương tác tức thì. Một trang điển hình nên có từ không đến ba preload, không phải hai mươi.

Dùng prefetch cho tài nguyên bắt buộc

Prefetch có mức ưu tiên thấp và mang tính tùy chọn. Đừng dùng nó cho asset mà trang hiện tại yêu cầu. Nếu trang cần nó ngay, hãy cân nhắc preload hoặc cơ chế phát hiện HTML thông thường.

Preconnect tới mọi bên thứ ba

Các trang nặng bên thứ ba thường có mười origin bên ngoài hoặc hơn. Preconnect tới tất cả chúng tạo ra nhiễu. Hãy chọn một hoặc hai origin vừa quan trọng vừa được dùng một cách có thể dự đoán.

Quên điều kiện di động

Gợi ý tài nguyên có giá trị nhất trên kết nối chậm hơn, nhưng cũng nguy hiểm nhất ở đó. Một prefetch lãng phí trên kết nối desktop nhanh chỉ là sai số nhỏ. Trên một gói di động bị giới hạn, đó là một đánh đổi tệ.

Một bảng quyết định đơn giản

| Tình huống | Gợi ý tốt nhất | Lý do | |---|---:|---| | Font quan trọng được phát hiện qua CSS | preload | Trang hiện tại cần nó, việc phát hiện bị muộn | | Hero image bị ẩn sau CSS hoặc client rendering | preload | Có thể cải thiện LCP nếu hình ảnh bắt đầu muộn | | Route kế tiếp có khả năng cao sau ý định của người dùng | prefetch | Giúp điều hướng tương lai mà không chặn trang hiện tại | | Origin font/API bên thứ ba quan trọng | preconnect | Loại bỏ bước thiết lập kết nối khỏi critical path | | Origin bên thứ ba có thể cần nhưng chưa chắc chắn | dns-prefetch hoặc không dùng | Chi phí thấp hơn, độ tin cậy thấp hơn | | Hình ảnh below-the-fold | không dùng | Hãy để lazy loading và mức ưu tiên của trình duyệt làm việc |

Quy tắc bình tĩnh

Gợi ý tài nguyên hoạt động tốt nhất khi chúng nhàm chán và cụ thể. Một font. Một hình ảnh LCP. Một origin bên thứ ba quan trọng. Một route kế tiếp có khả năng cao sau khi có ý định.

Chúng hoạt động kém khi được dùng như sự lạc quan: có thể người dùng sẽ cần thứ này, có thể trình duyệt nên tải thứ kia, có thể nhiều gợi ý hơn nghĩa là nhanh hơn.

Trình duyệt vốn đã tối ưu rất mạnh. Việc của bạn không phải là quản lý vi mô từng request. Việc của bạn là sửa vài trường hợp mà trình duyệt thiếu thông tin vào đúng thời điểm.

Câu hỏi thường gặp

Tôi có nên preload tất cả font của mình không?
Không. Chỉ preload các tệp font cần cho văn bản hiển thị sớm trong trang. Preload mọi độ đậm và kiểu chữ thường lãng phí băng thông và có thể trì hoãn các tài nguyên quan trọng hơn.
Prefetch có an toàn để dùng cho mọi liên kết nội bộ không?
Thường là không. Nó có thể tạo lưu lượng nền không cần thiết và lãng phí dữ liệu của người dùng. Hãy ưu tiên prefetch dựa trên ý định, chẳng hạn sau hover, focus, mở menu, hoặc một bước kế tiếp có thể dự đoán.
Sự khác biệt giữa preconnect và dns-prefetch là gì?
Preconnect thực hiện DNS, TCP, và TLS setup cho một origin. DNS-prefetch chỉ phân giải tên miền. Preconnect mạnh hơn nhưng tốn kém hơn, vì vậy chỉ nên dùng khi có độ tin cậy cao hơn.
Gợi ý tài nguyên có thể cải thiện Core Web Vitals không?
Có, đặc biệt là LCP, khi chúng khắc phục việc phát hiện muộn hoặc thiết lập kết nối cho một tài nguyên quan trọng. Chúng sẽ không giúp nếu vấn đề thực sự là asset quá lớn, phản hồi server chậm, code chặn render, hoặc caching kém.
Gợi ý tài nguyên nên được thêm trong HTML hay HTTP headers?
Cả hai đều có thể hiệu quả. HTML dễ suy luận hơn cho các gợi ý theo từng trang. HTTP Link headers có thể hữu ích khi server biết các tài nguyên quan trọng trước khi HTML được phân tích, nhưng chúng cần được kiểm thử cẩn thận để tránh trùng lặp hoặc gợi ý lỗi thời.

Nguồn & tài liệu tham khảo thêm

  1. MDN: rel=preload
  2. MDN: Resource hints
  3. web.dev: Preconnect and DNS-prefetch
  4. W3C: Resource Hints
Về tác giả
The Wux Webtools Team

Cập nhật lần cuối:

Tiếp tục đọc