2 cách tìm nạp trước: <link> thẻ và tiêu đề HTTP

Demián Renzulli
Demián Renzulli

Trong lớp học lập trình này, bạn sẽ triển khai tính năng tìm nạp trước theo 2 cách: bằng <link rel="prefetch"> và bằng tiêu đề HTTP Link.

Ứng dụng mẫu là một trang web có trang đích quảng bá với chiết khấu đặc biệt cho chiếc áo phông bán chạy nhất của cửa hàng. Vì trang đích liên kết đến một sản phẩm duy nhất, nên bạn có thể giả định rằng một tỷ lệ lớn người dùng sẽ chuyển đến trang chi tiết sản phẩm. Điều này khiến trang sản phẩm trở thành lựa chọn lý tưởng để tìm nạp trước trên trang đích.

Đo lường hiệu suất

Trước tiên, hãy thiết lập hiệu suất cơ sở:

  1. Nhấn tổ hợp phím `Control+Shift+J` (hoặc `Command+Option+J` trên máy Mac) để mở Công cụ cho nhà phát triển.
  2. Nhấp vào thẻ Mạng.

  3. Trong danh sách thả xuống Throttling (Điều tiết), hãy chọn Fast 3G (3G tốc độ cao) để mô phỏng một loại kết nối chậm.

  4. Để tải trang sản phẩm, hãy nhấp vào Mua ngay trong ứng dụng mẫu.

Trang product-details.html mất khoảng 600 mili giây để tải:

Bảng điều khiển Mạng cho thấy thời gian tải cho product-details.html

Để cải thiện khả năng điều hướng, hãy chèn thẻ prefetch vào trang đích để tìm nạp trước trang product-details.html:

  • Thêm phần tử <link> sau đây vào đầu tệp views/index.html:
<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">

      <link rel="prefetch" href="/product-details.html" as="document">
      ...
</head>

Thuộc tính as là không bắt buộc nhưng bạn nên sử dụng; thuộc tính này 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.

Cách xác minh rằng tính năng tìm nạp trước đang hoạt động:

  1. Nhấn tổ hợp phím `Control+Shift+J` (hoặc `Command+Option+J` trên máy Mac) để mở Công cụ cho nhà phát triển.
  2. Nhấp vào thẻ Mạng.

  3. Trong danh sách thả xuống Throttling (Điều tiết), hãy chọn Fast 3G (3G tốc độ cao) để mô phỏng một loại kết nối chậm.

  4. Xoá hộp đánh dấu Tắt bộ nhớ đệm.

  5. Tải lại ứng dụng.

Giờ đây, khi trang đích tải, trang product-details.html cũng tải, nhưng ở mức độ ưu tiên thấp nhất:

Bảng điều khiển Mạng cho thấy product-details.html được tìm nạp trước.

Trang này được lưu trong bộ nhớ đệm HTTP trong 5 phút, sau đó các quy tắc Cache-Control thông thường sẽ áp dụng cho tài liệu. Trong trường hợp này, product-details.html có tiêu đề cache-control với giá trị là public, max-age=0, tức là trang này sẽ được giữ lại trong tổng cộng 5 phút.

Đánh giá lại hiệu suất

  1. Tải lại ứng dụng.
  2. Để tải trang sản phẩm, hãy nhấp vào Mua ngay trong ứng dụng mẫu.

Hãy xem bảng điều khiển Mạng. Có 2 điểm khác biệt so với dấu vết mạng ban đầu:

  • Cột Kích thước cho biết "bộ nhớ đệm tìm nạp trước", tức là tài nguyên này được truy xuất từ bộ nhớ đệm của trình duyệt thay vì từ mạng.
  • Cột Thời gian cho thấy thời gian cần để tải tài liệu hiện là khoảng 10 mili giây.

Đây là mức giảm khoảng 98% so với phiên bản trước (mất khoảng 600 mili giây).

Bảng điều khiển Mạng hiển thị product-details.html được truy xuất từ bộ nhớ đệm tìm nạp trước.

Điểm cộng: Sử dụng prefetch làm một tính năng cải tiến tăng dần

Bạn nên triển khai tính năng tìm nạp trước dưới dạng một tính năng nâng cao tăng dần cho những người dùng đang duyệt web trên các kết nối nhanh. Bạn có thể sử dụng Network Information API để kiểm tra các điều kiện mạng và dựa vào đó để chèn các thẻ tìm nạp trước một cách linh hoạt. Nhờ đó, bạn có thể giảm thiểu mức tiêu thụ dữ liệu và tiết kiệm chi phí cho những người dùng sử dụng gói dữ liệu chậm hoặc đắt tiền.

Để triển khai tính năng tìm nạp trước thích ứng, trước tiên, hãy xoá thẻ <link rel="prefetch"> khỏi views/index.html:

<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
       <link rel="prefetch" href="/product-details.html" as="document">
       ...
    </head>

Sau đó, hãy thêm mã sau vào public/script.js để khai báo một hàm chèn thẻ prefetch một cách linh động khi người dùng đang sử dụng kết nối nhanh:

function injectLinkPrefetchIn4g(url) {
    if (window.navigator.connection.effectiveType === '4g') {
        //generate link prefetch tag
        const linkTag = document.createElement('link');
        linkTag.rel = 'prefetch';
        linkTag.href = url;
        linkTag.as = 'document';

        //inject tag in the head of the document
        document.head.appendChild(linkTag);
    }
}

Hàm này hoạt động như sau:

  • Thao tác này kiểm tra thuộc tính effectiveType của Network Information API để xác định xem người dùng có đang sử dụng kết nối 4G (hoặc nhanh hơn) hay không.
  • Nếu điều kiện đó được đáp ứng, thì điều kiện này sẽ tạo ra một thẻ <link> với prefetch là loại gợi ý, truyền URL sẽ được tìm nạp trước trong thuộc tính href và cho biết rằng tài nguyên là một document HTML trong thuộc tính as.
  • Cuối cùng, nó sẽ chèn tập lệnh một cách linh động vào head của trang.

Tiếp theo, hãy thêm script.js vào views/index.html, ngay trước thẻ </body> đóng:

<body>
      ...
      <script src="/script.js"></script>
</body>

Việc yêu cầu script.js ở cuối trang đảm bảo rằng script.js sẽ được tải và thực thi sau khi trang được phân tích cú pháp và tải.

Để đảm bảo rằng việc tìm nạp trước không ảnh hưởng đến các tài nguyên quan trọng cho trang hiện tại, hãy thêm đoạn mã sau để gọi injectLinkPrefetchIn4g() trên sự kiện window.load:

<body>
      ...
      <script src="/script.js"></script>
      <script>
           window.addEventListener('load', () => {
                injectLinkPrefetchIn4g('/product-details.html');
           });
      </script>
</body>

Giờ đây, trang đích chỉ tìm nạp trước product-details.html trên các kết nối nhanh. Để xác minh rằng:

  1. Nhấn tổ hợp phím `Control+Shift+J` (hoặc `Command+Option+J` trên máy Mac) để mở Công cụ cho nhà phát triển.
  2. Nhấp vào thẻ Mạng.
  3. Trong danh sách thả xuống Throttling (Điều tiết), hãy chọn Online (Trực tuyến).
  4. Tải lại ứng dụng.

Bạn sẽ thấy product-details.html trong bảng điều khiển Mạng:

Bảng điều khiển Mạng cho thấy product-details.html được tìm nạp trước.

Cách xác minh rằng trang sản phẩm không được tìm nạp trước trên các kết nối chậm:

  1. Trong danh sách thả xuống Throttling (Điều tiết), hãy chọn Slow 3G (3G chậm).
  2. Tải lại ứng dụng.

Bảng Mạng chỉ được chứa các tài nguyên cho trang đích mà không có product-details.html:

Bảng điều khiển Mạng cho thấy product-details.html không được tìm nạp trước.

Bạn có thể dùng tiêu đề HTTP Link để tìm nạp trước cùng loại tài nguyên như thẻ link. Việc quyết định thời điểm sử dụng một trong hai chủ yếu phụ thuộc vào lựa chọn ưu tiên của bạn, vì sự khác biệt về hiệu suất là không đáng kể. Trong trường hợp này, bạn sẽ sử dụng thuộc tính này để tìm nạp trước CSS chính của trang sản phẩm, nhằm cải thiện hơn nữa quá trình hiển thị.

Thêm tiêu đề HTTP Link cho style-product.css trong phản hồi của máy chủ cho trang đích:

  1. Mở tệp server.js và tìm trình xử lý get() cho url gốc: /.
  2. Thêm dòng sau vào đầu trình xử lý:
app.get('/', function(request, response) {
    response.set('Link', '</style-product.css>; rel=prefetch');
    response.sendFile(__dirname + '/views/index.html');
});
  1. Nhấn tổ hợp phím `Control+Shift+J` (hoặc `Command+Option+J` trên máy Mac) để mở Công cụ cho nhà phát triển.
  2. Nhấp vào thẻ Mạng.
  3. Tải lại ứng dụng.

style-product.css hiện được tìm nạp trước ở mức độ ưu tiên thấp nhất sau khi trang đích tải:

Bảng điều khiển Mạng cho thấy style-product.css được tìm nạp trước.

Để chuyển đến trang sản phẩm, hãy nhấp vào Mua ngay. Xem bảng điều khiển Mạng:

Bảng điều khiển Mạng cho thấy style-product.css được truy xuất từ bộ nhớ đệm tìm nạp trước.

Tệp style-product.css được truy xuất từ "bộ nhớ đệm tìm nạp trước" và chỉ mất 12 mili giây để tải.