Hình ảnh và các phần tử <iframe>
thường tiêu tốn nhiều băng thông hơn so với các loại tài nguyên khác. Trong trường hợp các phần tử <iframe>
, có thể mất thêm một khoảng thời gian xử lý đáng kể để tải và hiển thị các trang trong đó.
Trong trường hợp tải hình ảnh từng phần, việc trì hoãn tải hình ảnh nằm ngoài khung nhìn ban đầu có thể giúp giảm tình trạng tranh chấp băng thông cho các tài nguyên quan trọng hơn trong khung nhìn ban đầu. Điều này có thể cải thiện Thời gian hiển thị nội dung lớn nhất (LCP) của trang trong một số trường hợp kết nối mạng kém, và băng thông được phân bổ lại có thể giúp các đề xuất LCP tải và vẽ nhanh hơn.
Đối với các phần tử <iframe>
, bạn có thể cải thiện Lượt tương tác đến lượt vẽ tiếp theo (INP) của trang trong quá trình khởi động bằng cách tải từng phần tử một. Lý do là <iframe>
là một tài liệu HTML hoàn toàn riêng biệt với các tài nguyên phụ riêng.
Mặc dù các phần tử <iframe>
có thể chạy trong một quy trình riêng biệt, nhưng không có gì lạ khi các phần tử này chia sẻ một quy trình với các luồng khác. Điều này có thể tạo ra các điều kiện khiến các trang phản hồi ít hơn với hoạt động đầu vào của người dùng.
Do đó, việc trì hoãn việc tải hình ảnh ngoài màn hình và các phần tử <iframe>
là một kỹ thuật đáng theo đuổi và đòi hỏi nỗ lực khá thấp để có được lợi tức hợp lý về hiệu suất. Mô-đun này giải thích cách tải lười hai loại phần tử này để mang lại trải nghiệm người dùng nhanh hơn và tốt hơn trong giai đoạn khởi động quan trọng của trang.
Tải từng phần hình ảnh bằng thuộc tính loading
Bạn có thể thêm thuộc tính loading
vào các phần tử <img>
để cho trình duyệt biết cách tải các phần tử đó:
"eager"
thông báo cho trình duyệt rằng hình ảnh phải được tải ngay lập tức, ngay cả khi hình ảnh nằm ngoài khung nhìn ban đầu. Đây cũng là giá trị mặc định cho thuộc tínhloading
."lazy"
hoãn tải hình ảnh cho đến khi hình ảnh đó nằm trong khoảng cách đã đặt từ khung nhìn hiển thị. Khoảng cách này thay đổi tuỳ theo trình duyệt, nhưng thường được đặt đủ lớn để hình ảnh tải xong trước khi người dùng cuộn đến hình ảnh đó.
Ngoài ra, bạn cũng cần lưu ý rằng nếu đang sử dụng phần tử <picture>
, thì thuộc tính loading
vẫn phải được áp dụng cho phần tử con <img>
, chứ không phải phần tử <picture>
. Điều này là do phần tử <picture>
là một vùng chứa chứa các phần tử <source>
bổ sung trỏ đến nhiều đề xuất hình ảnh và đề xuất mà trình duyệt chọn được áp dụng trực tiếp cho phần tử <img>
con.
Không tải từng phần hình ảnh trong khung nhìn ban đầu
Bạn chỉ nên thêm thuộc tính loading="lazy"
vào các phần tử <img>
được đặt bên ngoài khung nhìn ban đầu. Tuy nhiên, việc biết vị trí chính xác của một phần tử tương ứng trong khung nhìn trước khi trang hiển thị có thể phức tạp. Bạn phải xem xét nhiều kích thước khung nhìn, tỷ lệ khung hình và thiết bị.
Ví dụ: khung nhìn trên máy tính để bàn có thể khác khá nhiều so với khung nhìn trên điện thoại di động vì khung nhìn này hiển thị nhiều không gian dọc hơn, có thể vừa với hình ảnh trong khung nhìn ban đầu mà không xuất hiện trong khung nhìn ban đầu của một thiết bị nhỏ hơn về mặt vật lý. Máy tính bảng dùng theo hướng dọc cũng hiển thị một lượng không gian dọc đáng kể, có thể nhiều hơn cả một số thiết bị máy tính để bàn.
Tuy nhiên, có một số trường hợp khá rõ ràng mà bạn nên tránh áp dụng loading="lazy"
. Ví dụ: bạn nhất định phải bỏ qua thuộc tính loading="lazy"
khỏi các phần tử <img>
trong trường hợp hình ảnh chính hoặc các trường hợp sử dụng hình ảnh khác mà các phần tử <img>
có thể xuất hiện phía trên đường gập hoặc gần đầu bố cục trên mọi thiết bị. Điều này càng quan trọng hơn đối với những hình ảnh có khả năng trở thành đề xuất LCP.
Hình ảnh được tải lười cần phải đợi trình duyệt hoàn tất bố cục để biết vị trí cuối cùng của hình ảnh có nằm trong khung nhìn hay không. Điều này có nghĩa là nếu một phần tử <img>
trong khung nhìn hiển thị có thuộc tính loading="lazy"
, thì phần tử đó chỉ được yêu cầu sau khi tất cả CSS được tải xuống, phân tích cú pháp và áp dụng cho trang, thay vì được tìm nạp ngay khi trình quét tải trước phát hiện phần tử đó trong mã đánh dấu thô.
Vì thuộc tính loading
trên phần tử <img>
được hỗ trợ trên tất cả trình duyệt chính, nên bạn không cần sử dụng JavaScript để tải hình ảnh từng phần, vì việc thêm JavaScript bổ sung vào trang để cung cấp các chức năng mà trình duyệt đã cung cấp sẽ ảnh hưởng đến các khía cạnh khác của hiệu suất trang, chẳng hạn như INP.
Bản minh hoạ tính năng tải từng phần hình ảnh
Tải từng phần các phần tử <iframe>
Tính năng tải từng phần các phần tử <iframe>
cho đến khi các phần tử đó hiển thị trong khung nhìn có thể giúp tiết kiệm dữ liệu quan trọng và cải thiện quá trình tải các tài nguyên quan trọng cần thiết để tải trang cấp cao nhất. Ngoài ra, vì các phần tử <iframe>
về cơ bản là toàn bộ tài liệu HTML được tải trong một tài liệu cấp cao nhất, nên các phần tử này có thể bao gồm một số lượng đáng kể tài nguyên phụ, đặc biệt là JavaScript, có thể ảnh hưởng đáng kể đến INP của trang nếu các tác vụ trong các khung đó yêu cầu thời gian xử lý đáng kể.
Nhúng bên thứ ba là một trường hợp sử dụng phổ biến cho các phần tử <iframe>
. Ví dụ: trình phát video được nhúng hoặc bài đăng trên mạng xã hội thường sử dụng các phần tử <iframe>
và thường yêu cầu một số lượng đáng kể tài nguyên phụ. Điều này cũng có thể dẫn đến tranh chấp băng thông cho tài nguyên của trang cấp cao nhất. Ví dụ: tính năng tải lười của một video được nhúng trên YouTube sẽ tiết kiệm hơn 500 KiB trong lần tải trang đầu tiên, trong khi tính năng tải lười của trình bổ trợ nút Thích trên Facebook sẽ tiết kiệm hơn 200 KiB, phần lớn là JavaScript.
Dù thế nào, mỗi khi có <iframe>
ở phần dưới cùng của trang, bạn nên cân nhắc việc tải từng phần nếu không cần thiết phải tải trước, vì việc này có thể cải thiện đáng kể trải nghiệm người dùng.
Thuộc tính loading
cho phần tử <iframe>
Thuộc tính loading
trên các phần tử <iframe>
cũng được hỗ trợ trong tất cả các trình duyệt chính. Giá trị của thuộc tính loading
và hành vi của các giá trị này giống như với các phần tử <img>
sử dụng thuộc tính loading
:
"eager"
là giá trị mặc định. Tệp này thông báo cho trình duyệt tải HTML của phần tử<iframe>
và tài nguyên phụ của phần tử đó ngay lập tức."lazy"
trì hoãn việc tải HTML của phần tử<iframe>
và các tài nguyên phụ của phần tử đó cho đến khi phần tử đó nằm trong khoảng cách đã xác định trước so với khung nhìn.
Bản minh hoạ về tính năng tải từng phần iframe
Mặt tiền
Thay vì tải nội dung nhúng ngay trong quá trình tải trang, bạn có thể tải nội dung đó theo yêu cầu để phản hồi tương tác của người dùng. Bạn có thể thực hiện việc này bằng cách hiển thị một hình ảnh hoặc một phần tử HTML thích hợp khác cho đến khi người dùng tương tác với hình ảnh hoặc phần tử đó. Sau khi người dùng tương tác với phần tử, bạn có thể thay thế phần tử đó bằng phần tử nhúng của bên thứ ba. Kỹ thuật này được gọi là facade (mặt tiền).
Một trường hợp sử dụng phổ biến của mặt tiền là nhúng video từ các dịch vụ bên thứ ba, trong đó việc nhúng có thể liên quan đến việc tải nhiều tài nguyên phụ bổ sung và có thể tốn kém (chẳng hạn như JavaScript) ngoài chính nội dung video. Trong trường hợp như vậy, trừ phi có nhu cầu chính đáng để video tự động phát, thì video được nhúng sẽ yêu cầu người dùng tương tác với video đó trước khi phát bằng cách nhấp vào nút phát.
Đây là cơ hội chính để hiển thị hình ảnh tĩnh có hình ảnh tương tự như video được nhúng và tiết kiệm đáng kể băng thông trong quá trình này. Sau khi người dùng nhấp vào hình ảnh, hình ảnh đó sẽ được thay thế bằng phần nhúng <iframe>
thực tế, kích hoạt HTML của phần tử <iframe>
bên thứ ba và tài nguyên phụ của phần tử đó để bắt đầu tải xuống.
Ngoài việc cải thiện tốc độ tải trang ban đầu, một điểm cộng quan trọng khác là nếu người dùng không bao giờ phát video, thì các tài nguyên cần thiết để phân phối video sẽ không bao giờ được tải xuống. Đây là một mẫu tốt vì đảm bảo người dùng chỉ tải xuống nội dung mà họ thực sự muốn, mà không đưa ra các giả định có thể không chính xác về nhu cầu của người dùng.
Tiện ích trò chuyện là một trường hợp sử dụng tuyệt vời khác cho kỹ thuật mặt tiền. Hầu hết các tiện ích trò chuyện đều tải xuống một lượng lớn JavaScript có thể ảnh hưởng tiêu cực đến việc tải trang và khả năng phản hồi đối với hoạt động đầu vào của người dùng. Giống như khi tải bất kỳ nội dung nào lên trước, chi phí sẽ phát sinh tại thời điểm tải, nhưng trong trường hợp tiện ích trò chuyện, không phải người dùng nào cũng có ý định tương tác với tiện ích đó.
Mặt khác, với một giao diện, bạn có thể thay thế nút "Bắt đầu trò chuyện" của bên thứ ba bằng một nút giả. Sau khi người dùng tương tác một cách có ý nghĩa với tiện ích này (chẳng hạn như giữ con trỏ trên tiện ích trong một khoảng thời gian hợp lý hoặc nhấp vào tiện ích), tiện ích trò chuyện thực tế và có chức năng sẽ được đưa vào vị trí khi người dùng cần.
Mặc dù bạn chắc chắn có thể tự tạo giao diện, nhưng có các tuỳ chọn nguồn mở cho các bên thứ ba phổ biến hơn, chẳng hạn như lite-youtube-embed
cho video trên YouTube, lite-vimeo-embed
cho video trên Vimeo và Trình tải Chat trực tiếp của React cho tiện ích trò chuyện.
Thư viện tải lười JavaScript
Nếu cần tải lười các phần tử <video>
, hình ảnh poster
của phần tử <video>
, hình ảnh được tải bằng thuộc tính CSS background-image
hoặc các phần tử không được hỗ trợ khác, bạn có thể thực hiện việc này bằng giải pháp tải lười dựa trên JavaScript, chẳng hạn như lazysizes hoặc yall.js, vì tính năng tải lười các loại tài nguyên này không phải là tính năng cấp trình duyệt.
Cụ thể, việc tự động phát và lặp lại các phần tử <video>
không có bản âm thanh là một giải pháp thay thế hiệu quả hơn nhiều so với việc sử dụng ảnh GIF động. Kích thước của ảnh GIF động thường lớn hơn tài nguyên video có chất lượng hình ảnh tương đương gấp vài lần. Tuy nhiên, những video này vẫn có thể tiêu tốn đáng kể băng thông, vì vậy, tính năng tải lười là một phương pháp tối ưu hoá bổ sung có thể giúp giảm đáng kể băng thông bị lãng phí.
Hầu hết các thư viện này hoạt động bằng cách sử dụng Intersection Observer API (API Trình quan sát giao nhau) và Mutation Observer API (API Trình quan sát thay đổi) nếu HTML của trang thay đổi sau lần tải đầu tiên để nhận biết thời điểm một phần tử đi vào khung nhìn của người dùng. Nếu hình ảnh hiển thị hoặc đang tiến đến khung nhìn, thì thư viện JavaScript sẽ thay thế thuộc tính không chuẩn (thường là data-src
hoặc một thuộc tính tương tự) bằng thuộc tính chính xác, chẳng hạn như src
.
Giả sử bạn có một video thay thế ảnh GIF động, nhưng bạn muốn tải lười video đó bằng giải pháp JavaScript. Bạn có thể làm việc này với yall.js bằng mẫu đánh dấu sau:
<!-- The autoplay, loop, muted, and playsinline attributes are to
ensure the video can autoplay without user intervention. -->
<video class="lazy" autoplay loop muted playsinline width="320" height="480">
<source data-src="video.webm" type="video/webm">
<source data-src="video.mp4" type="video/mp4">
</video>
Theo mặc định, yall.js quan sát tất cả các phần tử HTML đủ điều kiện có lớp "lazy"
. Sau khi yall.js được tải và thực thi trên trang, video sẽ không tải cho đến khi người dùng cuộn video vào khung nhìn. Tại thời điểm đó, các thuộc tính data-src
trên phần tử <source>
con của phần tử <video>
sẽ được hoán đổi thành các thuộc tính src
. Thao tác này sẽ gửi yêu cầu tải video xuống và tự động bắt đầu phát video.
Kiểm tra kiến thức của bạn
Giá trị mặc định của thuộc tính loading
cho cả phần tử <img>
và <iframe>
là gì?
"eager"
"lazy"
Khi nào bạn nên sử dụng giải pháp tải lười dựa trên JavaScript?
loading
, chẳng hạn như trong trường hợp video tự động phát nhằm thay thế hình ảnh động hoặc để tải lười hình ảnh áp phích của phần tử <video>
.
Khi nào mặt tiền là một kỹ thuật hữu ích?
Tiếp theo: Tìm nạp trước và kết xuất trước
Giờ đây, khi đã nắm được cách tải từng phần hình ảnh và các phần tử <iframe>
, bạn có thể đảm bảo rằng các trang có thể tải nhanh hơn trong khi vẫn đáp ứng nhu cầu của người dùng. Tuy nhiên, có một số trường hợp bạn nên tải tài nguyên theo phỏng đoán. Trong mô-đun tiếp theo, hãy tìm hiểu về tính năng tải trước và kết xuất trước, cũng như cách các kỹ thuật này (khi được sử dụng cẩn thận) có thể tăng tốc đáng kể việc điều hướng đến các trang tiếp theo bằng cách tải trước các trang đó.