雖然延遲載入圖片和影片對效能有良好且可評估成效的好處,但這不是輕微的工作。如果作業出錯,可能會導致非預期的結果。因此,請特別注意以下幾點。
摺疊式裝置
您可能會想要使用 JavaScript 延遲在網頁上每個媒體資源延遲載入,但您必須避免這種嘗試。不需捲動位置的任何項目都不應延遲載入。這類資源應視為重要資產,因此應正常載入。
延遲載入會延遲載入資源,直到指令碼完成載入並開始執行 DOM 後,才會延遲載入資源。對於需捲動位置的圖片,這是正常現象,但折疊位置上方的重要資源應以標準 <img>
元素載入,以便盡快顯示。
當然,摺疊式廣告日新月異,使用者在這麼多螢幕尺寸的螢幕上瀏覽網站時,還不太清楚可見。筆記型電腦上不需捲動位置的部分,有時可能會在行動裝置「下方」順利放置。無論哪種情況,我們沒有建議您以最適當的方式解決這個問題。您將需要彙整網頁中的重要資產,並依照正常的方式載入這些圖片。
此外,您可能也不希望折疊線過於嚴格,因為延遲載入的門檻才是高者。如果您比較需要建立位於折疊位置下方的緩衝區區域,以便圖片在使用者將圖片捲動至可視區域前開始順利載入,也許會比較合適。舉例來說,Intersection Observer API 可讓您在建立新的 IntersectionObserver
執行個體時,在選項物件中指定 rootMargin
屬性。這樣就能有效為元素提供緩衝區,進而在元素位於可視區域之前觸發延遲載入行為:
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
// lazy-loading image code goes here
}, {
rootMargin: "0px 0px 256px 0px"
});
如果 rootMargin
的值與您為 CSS margin
屬性指定的值看起來很像,那是因為這樣!在這種情況下,觀察到的元素底部邊界 (瀏覽器可視區域預設為瀏覽器可視區域,但可以使用 root
屬性變更為特定元素),並增加 256 像素。這表示當圖片元素在可視區域的 256 像素以內時,就會執行回呼函式,且圖片會在使用者實際看見圖片前開始載入。
如要在不支援 Intersection Observe 的瀏覽器中達到這項效果,請使用捲動事件處理程式碼,並調整 getBoundingClientRect
檢查以加入緩衝區。
版面配置位移和預留位置
如未使用預留位置,延遲載入媒體可能會導致版面配置變動。這些變更可能會對使用者造成困擾,並觸發耗用系統資源且導致卡頓的 DOM 版面配置作業。至少應考慮使用與目標圖片相同的尺寸的單色預留位置,或採用 LQIP 或 SQIP 等技巧,在載入媒體項目前提示媒體項目內容。
如果是 <img>
標記,src
一開始應指向某個預留位置,直到該屬性更新為最終圖片網址更新為止。在 <video>
元素中使用 poster
屬性,指向預留位置圖片。此外,請同時對 <img>
和 <video>
標記使用 width
和 height
屬性。這可確保在媒體載入時,從預留位置轉換為最終圖片不會改變元素的轉譯大小。
圖片解碼延遲
在 JavaScript 中載入大型圖片並拖放到 DOM 時,可能會串連主要執行緒,導致使用者介面在解碼期間短時間內沒有回應。先使用 decode
方法以非同步方式將圖片解碼,再將圖片插入 DOM 前,可能會減少這類卡頓問題,但需要注意的是:目前尚未開放所有國家/地區使用,這會讓延遲載入邏輯變得更加複雜。如要使用,請自行檢查。以下說明如何使用 Image.decode()
搭配備用:
var newImage = new Image();
newImage.src = "my-awesome-image.jpg";
if ("decode" in newImage) {
// Fancy decoding logic
newImage.decode().then(function() {
imageContainer.appendChild(newImage);
});
} else {
// Regular image load
imageContainer.appendChild(newImage);
}
請查看這個 CodePen 連結,查看類似實際應用範例的程式碼。如果大部分圖片都很小,對您而言可能沒有什麼限制,但一定可以在延遲載入大型圖片並插入 DOM 時,減少資源浪費。
內容未載入時
有時媒體資源因某種原因無法載入,並發生錯誤。可能在何時發生?視情況而定,但我們可以提出以下假設情況:您有一個短時間內 (例如五分鐘) 的 HTML 快取政策,且使用者造訪網站「或者」使用者開啟的分頁已過時 (例如數小時),並返回閱讀您的內容。這個過程中的某個時刻會出現重新部署。在此部署期間,映像檔資源名稱會因雜湊型版本管理而變更,或是完全移除。當使用者延遲載入圖片時,資源將無法使用,因而失敗。
雖然這種情況相當罕見,但如果延遲載入失敗,建議您建立備份方案。對圖片而言,這類解決方案大致如下:
var newImage = new Image();
newImage.src = "my-awesome-image.jpg";
newImage.onerror = function(){
// Decide what to do on error
};
newImage.onload = function(){
// Load the image
};
發生錯誤時,應如何處理,視應用程式而定。舉例來說,您可以將圖片預留位置區域替換成按鈕,讓使用者再次嘗試載入圖片,或單純在圖片預留位置區域顯示錯誤訊息。
其他情況也可能會發生。無論您採取何種做法,在發生錯誤時通知使用者都不是壞事,我們甚至可能在使用者發生異常時提供因應行動。
JavaScript 可用性
不應假設 JavaScript 隨時皆可使用。如果您要延遲載入圖片,建議您提供 <noscript>
標記,以便在 JavaScript 無法使用時顯示圖片。最簡單的備用示例包括在 JavaScript 關閉時使用 <noscript>
元素提供圖片:
如果 JavaScript 已關閉,使用者會同時看到預留位置圖片和 <noscript>
元素包含的圖片。如要解決這個問題,請在 <html>
標記上放置 no-js
的類別,如下所示:
<html class="no-js">
接著,在 <head>
中放置一行內嵌指令碼,然後透過 <link>
標記要求任何樣式表。當 JavaScript 開啟時,會從 <html>
元素移除 no-js
類別:
<script>document.documentElement.classList.remove("no-js");</script>
最後,使用某些 CSS 在無法使用 JavaScript 時隱藏延遲類別的元素:
.no-js .lazy {
display: none;
}
這樣做不會妨礙載入預留位置圖片,但結果較為理想。關閉 JavaScript 的使用者會看到預留位置圖片,比預留位置圖片更好,而且根本沒有有意義的圖片內容。