- 原文地址:Native image lazy-loading for the web!
- 原文做者:addyosmani
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:nanjingboy
- 校對者:xionglong58, portandbridge
在本文中,咱們將研究新的 loading
屬性,它爲 <img>
及 <iframe>
帶來了延遲加載的能力。若是你對此感興趣,可查看如下示例:javascript
<img src="celebration.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>
複製代碼
咱們但願在 ~Chrome 75 中爲 loading
提供支持,而且咱們正在深刻研究即將發佈的新特性。在此以前,讓咱們深刻了解它的工做原理。php
Web 頁面一般包含大量的圖片,這些圖片將影響網絡流量、頁面尺寸及頁面加載速度。這些圖片中許多處於屏幕外,每每須要用戶滾動頁面才能看到。html
過去,爲了下降屏幕外的圖片對頁面加載時間的影響,開發人員不得不使用 JavaScript 庫(好比:LazySizes)來推遲這些圖片的加載時機,直到用戶將頁面滾動到它們附近。前端
頁面加載 211 張圖片。沒有延遲加載的版本加載了 10 MB 數據。延遲加載版本(使用 LazySizes)僅預先加載了 250 KB 數據 - 其餘圖片將隨着用戶的滾動而加載。查看 WPT。java
若是瀏覽器就能幫你作到避免加載屏幕外的圖片呢?這將有助於加快視窗中內容的加載、減小總體網絡數據量以及低端設備下內存使用量。所以,我很高興地告訴你們,很快就可使用 image 和 iframe 的新屬性 loading
來實現了。android
loading
屬性loading
屬性容許瀏覽器推遲加載屏幕外的 image 和 iframe 直到用戶將頁面滾動到它們附近。loading
支持三個值:ios
lazy
:延遲加載。eager
:當即加載。auto
:由瀏覽器來決定是否延遲加載。若是不指定該屬性,其默認值爲 auto。git
HTML 標準 正在研究將 <img>
和 <iframe>
的 loading
屬性做爲標準的一部分。github
loading
屬性適用於 <img>
(包括包含 srcset
屬性及位於 <picture>
內部)和 <iframe>
:web
<!-- 延遲加載屏幕外的圖片直到用戶滾動到它附近 -->
<img src="unicorn.jpg" loading="lazy" alt=".."/>
<!-- 當即加載(而非延遲加載)圖片 -->
<img src="unicorn.jpg" loading="eager" alt=".."/>
<!-- 瀏覽器決定是否延遲加載圖片 -->
<img src="unicorn.jpg" loading="auto" alt=".."/>
<!-- 延遲加載 <picture> 內的圖片。<img> 用來驅動圖片的加載,所以 <picture> 及 srcset 會將合適的圖片呈如今 <img> 上 -->
<picture>
<source media="(min-width: 40em)" srcset="big.jpg 1x, big-hd.jpg 2x">
<source srcset="small.jpg 1x, small-hd.jpg 2x">
<img src="fallback.jpg" loading="lazy">
</picture>
<!-- 延遲加載設定 srcset 屬性的圖片-->
<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf" loading="lazy">
<!-- 延遲加載屏幕外的 iframe 直到用戶滾動到它附近 -->
<iframe src="video-player.html" loading="lazy"></iframe>
複製代碼
由瀏覽器完成「當用戶滾動到附近時」的確切檢測。通常來講,咱們但願瀏覽器在快要進入視窗口以前便開始提取延遲圖片和 iframe 的內容。這將增長圖片或 iframe 在用戶滾動到它們時完成加載的更改。
注意:我曾建議應該將 loading
屬性值做爲屬性名稱,由於它的命名與 decoding
屬性較爲接近。在以前的提議中,相似 lazyload
這樣的屬性沒有被接受,這是由於咱們須要支持多個值(lazy
、eager
及 auto
)。
咱們已知道爲延遲加載(跨瀏覽器支持)獲取及應用 JavaScript 庫的重要性。loading
的支持狀況能夠經過如下方式進行檢測:
<script> if ('loading' in HTMLImageElement.prototype) { // 瀏覽器支持 `loading`.. } else { // 獲取並應用 polyfill/JavaScript 類庫 // 來替代 lazy-loading。 } </script>
複製代碼
注意:你還可使用 loading
做爲一種漸進的加強功能。支持該屬性的瀏覽器可經過 loading=lazy
得到新的延遲加載能力,不支持該屬性的瀏覽器仍然會加載圖片。
若是跨瀏覽器支持圖片的延遲加載很是重要,那麼僅僅在使用 <img src=unicorn.jpg loading=lazy />
的標記中進行特性檢測、使用延遲加載庫是不夠的。
該標記需使用相似 <img data-src=unicorn.jpg />
(而非 src
、srcset
或 <source>
)的屬性,以免在不支持新屬性的瀏覽器下觸發馬上加載。若是瀏覽器支持 loading
,可使用 JavaScript 將這些屬性更改成正確的屬性,不然加載類庫。
下面是一個能夠說明其多是什麼樣子的例子。
<img>
標籤。data-src
會破壞預加載掃描程序,所以咱們但願避免它出如今視窗中的全部內容中。data-src
以免在不支持的瀏覽器中觸發馬上加載,若是瀏覽器支持 loading
,咱們將 data-src
替換爲 src
。loading
不被支持,咱們加載一個後備(LazySizes)腳本並啓動它。在這裏,咱們用 class=lazyload
向 LazySizes 指出,哪些圖片要延遲加載。<!-- 讓咱們在視窗內正常加載這個圖片 -->
<img src="hero.jpg" alt=".."/>
<!-- 讓咱們以延遲加載的方式加載剩餘圖片 -->
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/>
<script> (async () => { if ('loading' in HTMLImageElement.prototype) { const images = document.querySelectorAll("img.lazyload"); images.forEach(img => { img.src = img.dataset.src; }); } else { // 動態引入 LazySizes 庫 const lazySizesLib = await import('/lazysizes.min.js'); // 初始化 LazySizes(讀取 data-src & class=lazyload) lazySizes.init(); // lazySizes 在全局環境下工做。 } })(); </script>
複製代碼
看看這個!一個 loading=lazy
示例,展現了整整 100 張小貓圖片。
詳見 YouTube 視頻:youtu.be/bhnfL6ODM68
咱們強烈建議等到 loading
屬性處於穩定版本後再在你的生產環境中使用它。早期測試人員可能會發現如下註解很是有用。
轉到 chrome://flags
並同時開啓 "Enable lazy frame loading" 和 "Enable lazy image loading",而後從新啓動 Chrome。
Chrome 延遲加載的實現不只僅基於當前滾動位置的接近程度,還取決於網絡鏈接速度。對於不一樣的網絡鏈接速度,延遲加載 frame 和圖片的視窗距離閾值是硬編碼的,能夠經過命令行覆蓋該值。如下是一個覆蓋圖片延遲加載設置的示例:
canary --user-data-dir="$(mktemp -d)" --enable-features=LazyImageLoading --blink-settings=lazyImageLoadingDistanceThresholdPxUnknown=5000,lazyImageLoadingDistanceThresholdPxOffline=8000,lazyImageLoadingDistanceThresholdPxSlow2G=8000,lazyImageLoadingDistanceThresholdPx2G=6000,lazyImageLoadingDistanceThresholdPx3G=4000,lazyImageLoadingDistanceThresholdPx4G=3000 'https://mathiasbynens.be/demo/img-loading-lazy'
複製代碼
以上命令對應於(當前)默認配置。將全部值更改成 400
以便僅在滾動位置在距離圖片的 400 像素之內開始延遲加載。下面咱們還能夠看到距離閾值設爲 1 像素的另外一個作法(在本文前面的視頻中使用):
canary --user-data-dir="$(mktemp -d)" --enable-features=LazyImageLoading --blink-settings=lazyImageLoadingDistanceThresholdPxUnknown=1,lazyImageLoadingDistanceThresholdPxOffline=1,lazyImageLoadingDistanceThresholdPxSlow2G=1,lazyImageLoadingDistanceThresholdPx2G=1,lazyImageLoadingDistanceThresholdPx3G=1,lazyImageLoadingDistanceThresholdPx4G=1 'https://mathiasbynens.be/demo/img-loading-lazy'
複製代碼
因爲實如今將來幾周內穩定下來,咱們的默認配置極可能會發生變化。
Chrome 中 loading
的一個實現細節是它會在頁面加載時獲取前 2 KB 的圖片數據。若是服務器支持範圍請求,則前 2 KB 可能包含圖片尺寸。這使得咱們可以生成/顯示具備相同尺寸的佔位符。若是像是圖標一類的資源的話,前 2 KB 也頗有可能包含整幅圖片了。
Chrome 會在用戶即將看到圖片時抓取其剩餘數據。Chrome DevTools 中要注意的地方是,這可能致使(1)在 DevTools 的網絡面板中「出現」 兩次獲取和(2)爲每一個圖片提供兩個請求的資源定時。
loading
支持在一個美好的世界中,你不須要依賴客戶端上的 JavaScript 特性檢測來決定是否須要加載兼容庫 — 你須要在提供包含 JavaScript 延遲加載庫的 HTML 以前處理此問題。客戶端提示能夠啓用此類檢查。
傳遞 loading
參數的提示已經被考慮,但目前正處於早期討論階段。
試試看 <img loading>
,並讓咱們知道你的想法。我對你們如何探索跨瀏覽器的經驗,及是否有任何咱們錯過的邊緣狀況特別感興趣。
感謝 Simon Pieters、Yoav Weiss 和 Mathias Bynens 的反饋。很是感謝 Ben Greenstein、Scott Little、Raj T 和 Houssein Djirdeh 在 LazyLoad 上的工做。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。