Tải trước hình ảnh thích ứng

Bạn có thể tải trước hình ảnh thích ứng để hình ảnh tải nhanh hơn đáng kể bằng cách giúp trình duyệt xác định chính xác hình ảnh từ srcset trước khi hiển thị thẻ img.

Tổng quan về hình ảnh thích ứng

Hỗ trợ trình duyệt

  • Chrome: 73.
  • Edge: 79.
  • Firefox: 78.
  • Safari: 17.2.

Giả sử bạn đang duyệt web trên màn hình có chiều rộng 300 pixel và trang yêu cầu hình ảnh có chiều rộng 1500 pixel. Trang đó đã lãng phí rất nhiều dữ liệu di động vì màn hình của bạn không thể làm gì với tất cả độ phân giải thừa đó. Lý tưởng nhất là trình duyệt sẽ tìm nạp một phiên bản hình ảnh chỉ rộng hơn kích thước màn hình một chút, ví dụ: 325 pixel. Điều này đảm bảo hình ảnh có độ phân giải cao mà không lãng phí dữ liệu và giúp hình ảnh tải nhanh hơn.

Hình ảnh thích ứng cho phép trình duyệt tìm nạp nhiều tài nguyên hình ảnh cho nhiều thiết bị. Nếu bạn không sử dụng CDN hình ảnh, hãy lưu nhiều kích thước cho mỗi hình ảnh và chỉ định các kích thước đó trong thuộc tính srcset. Giá trị w cho trình duyệt biết chiều rộng của từng phiên bản để trình duyệt có thể chọn phiên bản phù hợp cho mọi thiết bị:

<img src="small.jpg" srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 1500w" alt="…">

Tổng quan về tính năng tải trước

Hỗ trợ trình duyệt

  • Chrome: 50.
  • Cạnh: ≤79.
  • Firefox: 85.
  • Safari: 11.1.

Nguồn

Tính năng tải trước cho phép bạn thông báo cho trình duyệt về các tài nguyên quan trọng mà bạn muốn tải ngay khi có thể, trước khi các tài nguyên đó được phát hiện trong HTML. Điều này đặc biệt hữu ích đối với các tài nguyên không dễ phát hiện, chẳng hạn như phông chữ có trong các tệp định kiểu, hình nền hoặc tài nguyên được tải từ tập lệnh.

<link rel="preload" as="image" href="important.png">

imagesrcsetimagesizes

Phần tử <link> sử dụng các thuộc tính imagesrcsetimagesizes để tải trước hình ảnh thích ứng. Sử dụng các phần tử này cùng với <link rel="preload">, với cú pháp srcsetsizes được dùng trong phần tử <img>.

Ví dụ: nếu bạn muốn tải trước một hình ảnh thích ứng được chỉ định bằng:

 <img src="wolf.jpg" srcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w" sizes="50vw" alt="A rad wolf">

Bạn có thể làm việc đó bằng cách thêm nội dung sau vào <head> của HTML:

<link rel="preload" as="image" href="wolf.jpg" imagesrcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w" imagesizes="50vw">

Thao tác này sẽ bắt đầu một yêu cầu bằng cách sử dụng cùng một logic lựa chọn tài nguyên mà srcsetsizes sử dụng.

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

Sau đây là một số trường hợp sử dụng để tải trước hình ảnh thích ứng.

Tải trước hình ảnh thích ứng được chèn động

Hãy tưởng tượng bạn đang tải hình ảnh chính một cách linh động trong một bản trình chiếu và bạn biết hình ảnh nào sẽ hiển thị trước tiên. Trong trường hợp đó, bạn nên hiển thị hình ảnh đó càng sớm càng tốt và không đợi tập lệnh trình chiếu tải hình ảnh đó.

Bạn có thể kiểm tra vấn đề này trên một trang web có thư viện hình ảnh được tải động:

  1. Mở bản minh hoạ trình chiếu này trong một thẻ mới.
  2. Nhấn Control+Shift+J (hoặc Command+Option+J trên máy Mac) để mở Công cụ cho nhà phát triển.
  3. Nhấp vào thẻ Mạng.
  4. Trong danh sách thả xuống Điều tiết, chọn 3G nhanh.
  5. Tắt hộp đánh dấu Tắt bộ nhớ đệm.
  6. Tải lại trang.
Bảng điều khiển Mạng trong Công cụ của Chrome cho nhà phát triển hiển thị một thác nước với tài nguyên JPEG chỉ bắt đầu tải xuống sau một số JavaScript.
Nếu không tải trước, hình ảnh sẽ bắt đầu tải sau khi trình duyệt chạy xong tập lệnh. Đối với hình ảnh đầu tiên, độ trễ đó là không cần thiết.

Việc sử dụng preload ở đây cho phép hình ảnh bắt đầu tải trước, vì vậy, hình ảnh có thể sẵn sàng hiển thị khi trình duyệt cần hiển thị hình ảnh đó.

Bảng điều khiển Mạng trong Công cụ của Chrome cho nhà phát triển hiển thị một thác nước với tài nguyên JPEG tải xuống song song với một số JavaScript.
Việc tải trước hình ảnh đầu tiên cho phép hình ảnh bắt đầu tải cùng lúc với tập lệnh.

Để xem sự khác biệt mà tính năng tải trước mang lại, hãy kiểm tra cùng một thư viện hình ảnh được tải động nhưng đã tải trước hình ảnh đầu tiên bằng cách làm theo các bước trong ví dụ đầu tiên.

Tải trước hình nền bằng image-set

Nếu có nhiều hình nền cho nhiều mật độ màn hình, bạn có thể chỉ định các hình nền đó trong CSS bằng cú pháp image-set. Sau đó, trình duyệt có thể chọn một trong các tỷ lệ khung hình để hiển thị dựa trên DPR của màn hình.

background-image: image-set( "cat.png" 1x, "cat-2x.png" 2x);

Vấn đề với hình nền CSS là trình duyệt chỉ phát hiện ra chúng sau khi đã tải xuống và xử lý tất cả CSS trong <head> của trang.

Bạn có thể kiểm tra vấn đề này trên một trang web mẫu có hình nền thích ứng.

Bảng điều khiển Mạng Công cụ của Chrome cho nhà phát triển hiển thị một thác nước có tài nguyên JPEG chỉ bắt đầu tải xuống sau một số CSS.
Trong ví dụ này, quá trình tải hình ảnh xuống sẽ không bắt đầu cho đến khi CSS được tải xuống hoàn toàn, gây ra độ trễ không cần thiết cho màn hình hiển thị hình ảnh.

Tính năng tải trước hình ảnh thích ứng giúp bạn tải những hình ảnh đó nhanh hơn.

<link rel="preload" as="image" imagesrcset="cat.png 1x, cat-2x.png 2x">

Việc bỏ qua thuộc tính href cho phép bạn đảm bảo rằng các trình duyệt không hỗ trợ imagesrcset trên phần tử <link> nhưng hỗ trợ image-set trong CSS sẽ tải nguồn chính xác xuống. Tuy nhiên, họ sẽ không được hưởng lợi từ tính năng tải trước trong trường hợp này.

Bạn có thể kiểm tra cách ví dụ trước hoạt động với hình nền thích ứng được tải trước trong bản minh hoạ tải trước hình nền thích ứng.

Bảng điều khiển Mạng trong Chrome DevTools hiển thị một thác nước với tài nguyên JPEG tải xuống song song với một số CSS.
Đây là hình ảnh và CSS bắt đầu tải xuống cùng lúc, cho phép tải hình ảnh nhanh hơn.

Hiệu quả thực tế của việc tải trước hình ảnh thích ứng

Về lý thuyết, việc tải trước hình ảnh thích ứng có thể giúp tăng tốc hình ảnh, nhưng thực tế thì sao?

Để trả lời câu hỏi đó, tôi đã tạo hai bản sao của một cửa hàng PWA minh hoạ: một cửa hàng không tải trước hình ảnh, và một cửa hàng tải trước một số hình ảnh. Vì trang web tải từng phần hình ảnh bằng JavaScript, nên bạn có thể hưởng lợi từ việc tải trước những hình ảnh xuất hiện trong khung nhìn ban đầu.

Điều đó đã tạo ra các kết quả sau đây cho không tải trước và cho tải trước hình ảnh:

  • Start Render (Bắt đầu kết xuất) vẫn giữ nguyên.
  • Chỉ số tốc độ cải thiện một chút (273 mili giây, vì hình ảnh đến nhanh hơn không chiếm nhiều pixel).
  • Last Painted Hero cải thiện đáng kể, tăng 1,2 giây.
Bản so sánh băng hình WebPageTest cho thấy hình ảnh được tải trước hiển thị nhanh hơn khoảng 1,5 giây.
Hình ảnh đến nhanh hơn đáng kể khi được tải trước, cải thiện đáng kể trải nghiệm người dùng.

Tải trước và <picture>

Nhóm làm việc về hiệu suất web đang thảo luận về việc thêm một tính năng tải trước tương đương cho srcsetsizes, nhưng không phải phần tử <picture>. Phần tử này xử lý trường hợp sử dụng "hướng dẫn nghệ thuật".

Vẫn còn một số vấn đề kỹ thuật cần giải quyết để tải trước <picture>, nhưng trong thời gian chờ đợi, bạn có thể áp dụng các giải pháp sau:

<picture>
    <source srcset="small_cat.jpg" media="(max-width: 400px)">
    <source srcset="medium_cat.jpg" media="(max-width: 800px)">
    <img src="large_cat.jpg">
</picture>

Logic lựa chọn nguồn hình ảnh của phần tử <picture> sẽ lần lượt xem xét các thuộc tính media của phần tử <source>, tìm thuộc tính đầu tiên khớp và sử dụng tài nguyên đính kèm.

Vì tính năng tải trước thích ứng không có khái niệm "thứ tự" hoặc "khớp đầu tiên", nên bạn sẽ cần dịch các điểm ngắt thành những nội dung như sau:

<link rel="preload" href="small_cat.jpg" as="image" media="(max-width: 400px)">
<link rel="preload" href="medium_cat.jpg" as="image" media="(min-width: 400.1px) and (max-width: 800px)">
<link rel="preload" href="large_cat.jpg" as="image" media="(min-width: 800.1px)">

Tải trước và type

Phần tử <picture> cũng hỗ trợ so khớp trên type đầu tiên, cho phép bạn cung cấp nhiều định dạng hình ảnh để trình duyệt có thể chọn định dạng hình ảnh đầu tiên mà trình duyệt hỗ trợ. Trường hợp sử dụng này không được hỗ trợ tính năng tải trước.

Đối với các trang web sử dụng tính năng so khớp kiểu, bạn nên tránh tải trước và thay vào đó, hãy để trình quét tải trước chọn hình ảnh từ các phần tử <picture><source>. Dù sao, đây cũng là phương pháp hay nhất, đặc biệt là khi sử dụng Mức độ ưu tiên tìm nạp để giúp ưu tiên hình ảnh phù hợp.

Ảnh hưởng đến Thời gian hiển thị nội dung lớn nhất (LCP)

Vì hình ảnh có thể là thành phần đề xuất cho Thời gian hiển thị nội dung lớn nhất (LCP), nên việc tải trước hình ảnh có thể cải thiện LCP của trang web.

Bất kể hình ảnh bạn đang tải trước có thích ứng hay không, tính năng tải trước sẽ hoạt động tốt nhất khi tài nguyên hình ảnh không được phát hiện trong tải trọng đánh dấu ban đầu. Bạn cũng sẽ cải thiện được nhiều hơn về LCP trên những trang web hiển thị mã đánh dấu ở phía máy khách so với những trang web gửi mã đánh dấu hoàn chỉnh từ máy chủ.