Try   HackMD

透過瀏覽器機制從預先載入響應式圖片提升效能

本篇文章將基於「瀏覽器方」所提供的原生解法來看看要如何透過預先載入(Preload)技術,來提升網頁效能。

預先載入圖片

考慮到商業需求,有時候產品網站需要利用圖片來突顯產品特色,或者用視覺效果來吸引消費者。在這種無法避免使用圖片的情境下,如何同時確保網站效能就變成了開發者的重要挑戰。

實作方法

透過 link 元素中的 rel="preload" 我們主動告知瀏覽器希望能夠盡快載入的關鍵資源:

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

而從 Netkwork 觀測 Waterfall,可以觀察到在正常載入下未特別處理的頁面 request 順序原先如下:

正常載入

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • index.html
  • a.js
  • important.png

而經由 Preload 處理過後的圖片 request 比起原先的順序還要更早。

經由 Preload 處理

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • index.html
  • important.png
  • a.js

經過 Preload 處理後,除了圖片加載時間在總體來說變得更快之外,對於 Core Web Vitals 中的指標 Largest Contentful Paint(LCP) 也有顯著影響,這是因為 LCP 最主要是觀測第一畫面(First View)中的最大資源載入時間,而圖片本身即為 LCP 關注的「候選對象」之一,基本上前幾名大概率都偏離不了圖片資源,也就是說加快圖片載入的同時也是在提升 LCP 指標。

要注意之處

要小心的是我們並非所有圖片都是需要進行 Preload 的,也就是說除了載入畫面原先的圖片之外,需要卷軸下滑等等才能瀏覽到的圖片基本上我們會透過類似 LazyLoad 的方式來進行處理。

要透過瀏覽器原生的實作可在 img 元素上加上 loading="lazy" 部分:

<img src="notInFirstView.jpg" loading="lazy" alt="..." />

另一種常見策略是透過 JavaScript 去控制,比方透過 Intersection Observer API 去偵測該元素是否進入瀏覽視野來判定是否真的要去要求(request)圖片資源。

// 寫下監聽邏輯
const lazyImageObserver = new IntersectionObserver(function(entries, observer) {
    entries.forEach(function(entry) {
        // 監聽邏輯:是否進入視野 (當然也可以設定距離多少)
        if (entry.isIntersecting) {
            let lazyImage = entry.target
            lazyImage.src = lazyImage.dataset.src
            lazyImage.classList.remove('lazyload')
            lazyImageObserver.unobserve(lazyImage)
        }
    })
})

// 取得目前所有 class name 含有 lazyload 的圖片
const lazyImages = [].slice.call(document.querySelectorAll('img.lazyload'))
// 加上監聽邏輯
lazyImages.forEach(function(lazyImage) {
    lazyImageObserver.observe(lazyImage)
})

預先載入響應式圖片

而上述提及的預先載入方法其實主要是用於 img 元素只有單張的圖片,然後專案架構如果是設計 RWD 的情況下,為了效能考量我們有時候會在 img 元素上加上 srcset 來控制應該載入哪種尺寸的圖片,來優化效能。

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

這時候如果我們想透過 Preload 機制的話就需要改寫成這樣:

<link rel="preload" as="image" href="responsive.jpg" imagesrcset="small.jpg 500w, medium.jpg 1000w, large.jpg 1500w" imagesizes="50vw">

接著就可以依照原先響應式邏輯預載入圖片。

要注意之處

另外,有另外一種處理方式,也是常用來處理響應式圖片的寫法之一,就是透過 CSS 中的 background-image 中的 image-set 來處理:

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

但是透過這種做法的缺點是瀏覽器可能要處理頁面中的其他 css 後可能才會發現有其設定,所以如果是用來處理 first view 中的圖片對於效能來說可能相較就比較差一些。

那以上就是透過瀏覽器方提供的機制,來預先載入響應式圖片提升效能的做法,如果你有其他方式也歡迎投稿或留言!

--End--


社群工商

LearnWeb Taiwan 旨在交流網頁領域相關技術與產品開發經驗,領域包含但不限於「前端」/「後端」/「UI、UX」/「PM」等職務相關內容。

我們相信對於本身職務垂直縱深的專業能力,搭配相關領域知識的橫向理解,能夠促使產品帶給使用者更好的使用體驗。

因此,我們不定時會舉辦工作坊、講座、小聚等等活動,媒合各個領域的專業人才前來交流;此外也盡可能提供第一手產業新知給大家,希望促進台灣網頁相關領域的產品能夠更加良好!

若你對我們有興趣,歡迎依照自己所需加入各個平台喔!

官方平台 適合對象
Discord 社群
  • 想關注最新活動資訊
  • 推播屬於你的產業新聞資訊
  • 想閒聊、認識相關產業的朋友!
Facebook 社團
Facebook 粉專
  • 想關注最新活動資訊
  • 綜合資訊新聞(我全都要!)
Instagram 相片牆
  • 想關注最新活動資訊
  • 線下活動照片紀念
  • 第一手社群周邊資訊

贊助社群營運