Tìm nạp trước tài nguyên để tăng tốc độ di chuyển trong tương lai

Tìm hiểu về gợi ý tài nguyên rel=prefetch và cách sử dụng gợi ý này.

Nghiên cứu cho thấy rằng thời gian tải nhanh hơn sẽ giúp tăng tỷ lệ chuyển đổi và mang lại trải nghiệm tốt hơn cho người dùng. Nếu có thông tin chi tiết về cách người dùng di chuyển trên trang web của bạn và những trang mà họ có thể truy cập tiếp theo, bạn có thể cải thiện thời gian tải của các thao tác điều hướng trong tương lai bằng cách tải trước tài nguyên cho các trang đó.

Hướng dẫn này giải thích cách thực hiện việc đó bằng <link rel=prefetch>, một gợi ý tài nguyên cho phép bạn triển khai tính năng tải trước một cách dễ dàng và hiệu quả.

Cải thiện cách thao tác bằng rel=prefetch

Khi thêm <link rel=prefetch> vào một trang web, trình duyệt sẽ yêu cầu trình duyệt tải toàn bộ trang hoặc một số tài nguyên (như tập lệnh hoặc tệp CSS) mà người dùng có thể cần trong tương lai xuống:

<link rel="prefetch" href="/articles/" as="document">

Sơ đồ minh hoạ cách hoạt động của tính năng tìm nạp trước đường liên kết.

Gợi ý prefetch sẽ tiêu tốn thêm vài byte cho các tài nguyên không cần thiết ngay lập tức, vì vậy, bạn cần áp dụng kỹ thuật này một cách thận trọng; chỉ tải trước tài nguyên khi bạn chắc chắn rằng người dùng sẽ cần đến chúng. Cân nhắc không tìm nạp trước khi người dùng sử dụng kết nối chậm. Bạn có thể phát hiện điều đó bằng API Thông tin mạng.

Có nhiều cách để xác định đường liên kết nào cần tải trước. Cách đơn giản nhất là tìm nạp trước đường liên kết đầu tiên hoặc một vài đường liên kết đầu tiên trên trang hiện tại. Ngoài ra, cũng có những thư viện sử dụng các phương pháp phức tạp hơn. Chúng tôi sẽ giải thích về những phương pháp này ở phần sau của bài đăng này.

Trường hợp sử dụng

Tải trước các trang tiếp theo

Tìm nạp trước tài liệu HTML khi các trang tiếp theo có thể dự đoán được, để khi người dùng nhấp vào một đường liên kết, trang sẽ được tải ngay lập tức.

Ví dụ: trong trang thông tin sản phẩm, bạn có thể tải trước trang cho sản phẩm phổ biến nhất trong danh sách. Trong một số trường hợp, thao tác điều hướng tiếp theo thậm chí còn dễ dự đoán hơn – trên trang giỏ hàng, khả năng người dùng truy cập vào trang thanh toán thường rất cao, điều này khiến trang này trở thành một ứng cử viên phù hợp để tải trước.

Mặc dù việc tải trước tài nguyên sẽ sử dụng thêm băng thông, nhưng nó có thể cải thiện hầu hết các chỉ số hiệu suất. Thời gian tải byte đầu tiên (TTFB) thường sẽ thấp hơn nhiều, vì yêu cầu tài liệu dẫn đến một lượt truy cập vào bộ nhớ đệm. Vì TTFB sẽ thấp hơn, nên các chỉ số theo thời gian tiếp theo cũng thường thấp hơn, bao gồm cả Nội dung lớn nhất hiển thị (LCP)Lượt hiển thị nội dung đầu tiên (FCP).

Tải trước các thành phần tĩnh

Tìm nạp trước các thành phần tĩnh, chẳng hạn như tập lệnh hoặc tệp kiểu, khi có thể dự đoán các phần tiếp theo mà người dùng có thể truy cập. Điều này đặc biệt hữu ích khi các thành phần đó được chia sẻ trên nhiều trang.

Ví dụ: Netflix tận dụng thời gian người dùng dành cho các trang đã đăng xuất để tải trước React. React sẽ được sử dụng sau khi người dùng đăng nhập. Nhờ đó, họ giảm 30% Thời gian phản hồi cho các thao tác điều hướng trong tương lai.

Ảnh hưởng của việc tải trước thành phần tĩnh đối với các chỉ số hiệu suất phụ thuộc vào tài nguyên đang được tải trước:

  • Việc tìm nạp trước hình ảnh có thể làm giảm đáng kể thời gian LCP của các phần tử hình ảnh LCP.
  • Việc tìm nạp trước biểu định kiểu có thể cải thiện cả FCP và LCP, vì thời gian trên mạng để tải biểu định kiểu xuống sẽ bị loại bỏ. Vì các tệp kiểu đang chặn quá trình kết xuất, nên chúng có thể làm giảm LCP khi được tìm nạp trước. Trong trường hợp phần tử LCP của trang tiếp theo là hình nền CSS được yêu cầu thông qua thuộc tính background-image, hình ảnh đó cũng sẽ được tìm nạp trước dưới dạng tài nguyên phụ thuộc của bảng kiểu được tìm nạp trước.
  • Việc tìm nạp trước JavaScript sẽ cho phép quá trình xử lý tập lệnh được tìm nạp trước diễn ra sớm hơn nhiều so với khi tập lệnh này được mạng yêu cầu tìm nạp trước trong quá trình điều hướng. Điều này có thể ảnh hưởng đến Lượt tương tác đến nội dung hiển thị tiếp theo (INP) của trang. Trong trường hợp đánh dấu được hiển thị trên ứng dụng thông qua JavaScript, bạn có thể cải thiện LCP bằng cách giảm độ trễ tải tài nguyên và hiển thị phía máy khách của phần đánh dấu chứa phần tử LCP của trang có thể xảy ra sớm hơn.
  • Việc tải trước phông chữ web mà trang hiện tại chưa sử dụng có thể loại bỏ các thay đổi bố cục. Trong trường hợp sử dụng font-display: swap;, khoảng thời gian hoán đổi cho phông chữ sẽ bị loại bỏ, giúp hiển thị văn bản nhanh hơn và loại bỏ các thay đổi bố cục. Nếu một trang trong tương lai sử dụng phông chữ được tìm nạp trước và phần tử LCP của trang là một khối văn bản sử dụng phông chữ web, thì LCP cho phần tử đó cũng sẽ nhanh hơn.

Tìm nạp trước các đoạn JavaScript theo yêu cầu

Tính năng phân tách mã các gói JavaScript cho phép bạn ban đầu chỉ tải một số phần của ứng dụng và tải lười phần còn lại. Nếu đang sử dụng kỹ thuật này, bạn có thể áp dụng tính năng tải trước cho các tuyến hoặc thành phần không cần thiết ngay lập tức nhưng có thể sẽ sớm được yêu cầu.

Ví dụ: nếu có một trang chứa nút mở hộp thoại có bộ chọn biểu tượng cảm xúc, bạn có thể chia trang đó thành ba phần JavaScript – trang chủ, hộp thoại và bộ chọn. Trang chủ và hộp thoại có thể được tải ban đầu nhưng có thể tải bộ chọn theo yêu cầu. Các công cụ như webpack cho phép bạn hướng dẫn trình duyệt tải trước các đoạn theo yêu cầu này.

Cách triển khai rel=prefetch

Cách đơn giản nhất để triển khai prefetch là thêm thẻ <link> vào <head> của tài liệu:

<head>
  ...
  <link rel="prefetch" href="/articles/" as="document">
  ...
</head>

Thuộc tính as giúp trình duyệt đặt đúng tiêu đề và xác định xem tài nguyên đã có trong bộ nhớ đệm hay chưa. Các giá trị ví dụ cho thuộc tính này bao gồm: document, script, style, font, imagecác giá trị khác.

Bạn cũng có thể bắt đầu tải trước qua tiêu đề HTTP Link:

Link: </css/style.css>; rel=prefetch

Lợi ích của việc chỉ định gợi ý tải trước trong Tiêu đề HTTP là trình duyệt không cần phân tích cú pháp tài liệu để tìm gợi ý tài nguyên. Điều này có thể cải thiện một chút trong một số trường hợp.

Tìm nạp trước các mô-đun JavaScript bằng nhận xét ma thuật webpack

webpack cho phép bạn tải trước tập lệnh cho các tuyến hoặc chức năng mà bạn chắc chắn rằng người dùng sẽ sớm truy cập hoặc sử dụng.

Đoạn mã sau đây tải từng phần một chức năng sắp xếp từ thư viện lodash để sắp xếp một nhóm số sẽ được gửi bằng một biểu mẫu:

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

Thay vì chờ sự kiện "gửi" diễn ra để tải chức năng này, bạn có thể tìm nạp trước tài nguyên này để tăng khả năng có tài nguyên đó trong bộ nhớ đệm vào thời điểm người dùng gửi biểu mẫu. webpack cho phép việc đó bằng cách sử dụng nhận xét ma thuật bên trong import():

form.addEventListener("submit", e => {
   e.preventDefault()
   import(/* webpackPrefetch: true */ 'lodash.sortby')
         .then(module => module.default)
         .then(sortInput())
         .catch(err => { alert(err) });
});

Thao tác này sẽ yêu cầu webpack chèn thẻ <link rel="prefetch"> vào tài liệu HTML:

<link rel="prefetch" as="script" href="1.bundle.js">

Lợi ích về hiệu suất của việc tải trước các đoạn theo yêu cầu có chút khác biệt, nhưng nói chung, bạn có thể thấy phản hồi nhanh hơn đối với các lượt tương tác phụ thuộc vào các đoạn theo yêu cầu đó, vì các đoạn này sẽ có sẵn ngay lập tức. Tuỳ thuộc vào bản chất của lượt tương tác, điều này có thể mang lại lợi ích cho INP của trang.

Nói chung, tính năng tìm nạp trước cũng ảnh hưởng đến trình tự ưu tiên tài nguyên tổng thể. Khi một tài nguyên được tìm nạp trước, tài nguyên đó sẽ được thực hiện ở mức độ ưu tiên thấp nhất có thể. Do đó, mọi tài nguyên được tìm nạp trước sẽ không cạnh tranh về băng thông cho các tài nguyên cần thiết của trang hiện tại.

Bạn cũng có thể triển khai tính năng tải trước thông minh hơn bằng các thư viện sử dụng prefetch:

  • quicklink sử dụng Intersection Observer API để phát hiện thời điểm các đường liên kết xuất hiện trong khung nhìn và tải trước các tài nguyên được liên kết trong thời gian rảnh. Phần thưởng: đường liên kết nhanh có kích thước dưới 1 KB!
  • Guess.js sử dụng các báo cáo phân tích để xây dựng mô hình dự đoán dùng để tìm nạp trước thông minh chỉ những thông tin mà người dùng có khả năng cần.

Cả quicklink và giả.js đều sử dụng Network Information API để tránh tìm nạp trước nếu người dùng đang sử dụng mạng chậm hoặc đã bật Save-Data.

Tìm nạp trước nâng cao

Gợi ý về tài nguyên không phải là hướng dẫn bắt buộc. Trình duyệt sẽ quyết định xem có thực thi hay không và khi nào các gợi ý này được thực thi.

Bạn có thể sử dụng tính năng tải trước nhiều lần trong cùng một trang. Trình duyệt sẽ đưa tất cả gợi ý vào hàng đợi và yêu cầu từng tài nguyên khi rảnh. Trong Chrome, nếu một nội dung tìm nạp trước chưa tải xong và người dùng chuyển đến tài nguyên tìm nạp trước đã định sẵn, thì tải trong quá trình sẽ được trình duyệt chọn làm thao tác điều hướng (các nhà cung cấp trình duyệt khác có thể triển khai thao tác này theo cách khác).

Tính năng tìm nạp trước diễn ra ở mức độ ưu tiên "Thấp nhất", vì vậy, các tài nguyên được tìm nạp trước không cạnh tranh băng thông với các tài nguyên cần thiết trong trang hiện tại.

Các tệp đã tìm nạp trước được lưu trữ trong Bộ nhớ đệm HTTP hoặc bộ nhớ đệm của bộ nhớ (tuỳ thuộc vào việc tài nguyên có thể lưu vào bộ nhớ đệm hay không) trong một khoảng thời gian khác nhau tuỳ theo trình duyệt. Ví dụ: trong Chrome, các tài nguyên được giữ lại trong khoảng 5 phút, sau đó các quy tắc Cache-Control thông thường cho tài nguyên sẽ được áp dụng.

Kết luận

Việc sử dụng prefetch có thể cải thiện đáng kể thời gian tải của các thao tác điều hướng trong tương lai và thậm chí khiến các trang có vẻ như tải tức thì. prefetch được hỗ trợ rộng rãi trong các trình duyệt hiện đại, khiến đây là một kỹ thuật hấp dẫn để cải thiện trải nghiệm điều hướng cho nhiều người dùng. Kỹ thuật này yêu cầu tải thêm các byte có thể không dùng đến, vì vậy hãy lưu ý khi sử dụng kỹ thuật này; chỉ thực hiện khi cần thiết và tốt nhất là chỉ thực hiện trên các mạng nhanh.