圖片最佳化(Image Optimization)

實作「圖片最佳化(Image Optimization)」的第一個問題是「真的需要這個圖檔嗎?」,去除不需要的圖檔即可減少 HTTP Request。第二個問題才是「若圖檔不能去除或被取代,可以做哪些優化?」。

#1 取代圖檔

#2 選擇適合的圖片類型並壓縮

在高解析度螢幕下,優先選用向量圖檔;若使用點陣圖檔,則高解析度的螢幕需要高解析度的圖片才能讓畫面更清晰,但檔案大小較大,必須儘量優化。

如何選擇適合的圖片類型?

如何在這兩者之間做選擇?向量圖檔(Vector images)和點陣圖檔(Raster images),兩者差別在於是否受縮放和解析度調整的影響。

最佳化向量圖檔

最佳化 SVG 的方式是

最佳化點陣圖檔

最佳化點陣圖檔的方式是

#3 選擇適合的圖片格式和相關壓縮設定

選擇正確的圖片格式。

圖片壓縮格式

圖片來源:Image Optimization

一些技巧…

#4 Responsive Images

響應式網頁會根據視窗大小決定圖檔尺寸,因此為了顧及圖檔解碼和調整大小的成本,避免放置過度不合尺寸的圖片,可使用 <picture>/<img srcset sizes>

範例如下,若螢幕寬度超過 650px,顯示 img_pink_flowers.jpg 這張圖;若螢幕寬度超過 465px 以上但在 650px 以下,顯示 img_white_flower.jpg 這張圖;若在 465px 以下,則顯示 img_orange_flowers.jpg 這張圖。

<picture>
  <source media="(min-width: 650px)" srcset="img_pink_flowers.jpg">
  <source media="(min-width: 465px)" srcset="img_white_flower.jpg">
  <img src="img_orange_flowers.jpg" alt="Flowers" style="width:auto;">
</picture>

#5 Image Caching

正確設定快取規則可減少圖片下載數,請參考-HTTP Caching

#6 Resource Hints

預先下載資源可讓使用者有更快看到畫面的錯覺。

主要會用到 preload點此比較 Preload 與 Prefetch 的異同。

注意,不需預先下載 (1) 沒有受到廣泛瀏覽器支援的格式的圖檔,例如 WebP;(2) 響應式網頁下使用 srcset 根據設備條件定義的圖片。

提示瀏覽器當前頁面會用到 script.js,儘早下載它,屬性 as 用來告知資源的類型,若不設定則優先權會非常低。

<link rel="preload" href="script.js" as="script" />

也可使用 HTTP Link header。

Link: <https://example.com/script.js>; rel=preload; as=script

屬性 onload 可在下載完成後做些事情。

<link rel="preload" as="script" href="script.js" onload="console.log('Hello World!')">

屬性 media 可依需求下載不同資源。

<link rel="preload" as="image" href="map.png" media="(max-width: 600px)">
<link rel="preload" as="script" href="map.js" media="(min-width: 601px)">

在瀏覽器支援度上,桌機方面,Chrome 和 Safari 有支援、Edge 部份支援、Firefox 和 IE 不支援;手機方面,iOS Safari、Chrome for Android 新版瀏覽器是支援的。

preload 瀏覽器支援度

圖片來源:Resource Hints: preload

其他還有

#7 CDN

CDN 透過設備的檢測、即時圖檔優化(調整大小、剪裁和過濾)和目前離使用者距離最近的 CDN 快取來提供圖片,比較服務

#8 Lazy Loading

避免下載使用者不會用到的資源,推薦工具

簡單範例如下,先使用 placeholder 佔用空間,等使用者滑到該位置前,再用 JavaScript 將正確的圖片替換掉 placeholder。

<img>

<img
  class="lazy"
  src="placeholder-image.jpg"
  data-src="image-to-lazy-load-1x.jpg"
  data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x"
  alt="I'm an image!"
>

範例

CSS Background

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

範例

#9 Sprites

由於取得每張圖片都需要一次 HTTP 請求,因此將小圖併為一張圖,這樣就只需要一次 HTTP 請求,優點是減少 HTTP 請求次數即可減少畫面載入時間,缺點是 (1) 需要使用額外工具維護;(2) 圖檔編排可能需要空白而導致檔案體積較大;(3) 樣式定位若沒有設定好會有滲透(Bleedthrough)的問題。

但在 HTTP/2 的狀況下就不需要 Sprites 了。

#10 利用工具檢視效能

簡單地手動檢測

設定目標、自動檢測

參考資料


comments powered by Disqus