[鐵人賽 2022-擊敗前端面試大作戰] Image ant text optimization
今天要來針對昨天討論到 core web vital 的優化方法做更深入的討論!記得昨天討論到 Largest Contentful Paint(LCP),然後我們有講到要解決 LCP 的一個方法就是假如畫面中有大型照片的話可以使用畫面優化來減少 LCP 的數字!今天就會針對照片的優化來討論,會講到以下四種優化圖片的方式:
- preload
- 使用合適的圖片格式
- 用 image CDN
- 線上壓縮圖片
preload 的功能?
preload 是<link>
裡面的一個 type,它可以告訴瀏覽器該資源需要提早載入,而能夠被 preload 的有 image,audio,style, video 等等。
使用方法
//假設我們有一個img長這樣
<img src="wolf.jpg" srcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w" sizes="50vw" alt="A rad wolf">
//那在 link 裡我們就可以適用 preload 的方式來預先載入該圖片
<link rel="preload" as="image" href="wolf.jpg" imagesrcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w" imagesizes="50vw">
注意:過度使用 preload 反而會造成冷效果
額外補充: preload vs prefetch vs preconnect
這三種功能都是用在 link 的 rel(relationship) tag 裡做使用,來辨別出該 link 的重要性跟優先順序。
https://shubo.io/preload-prefetch-preconnect/#caching-%E8%A1%8C%E7%82%BA
preload:用於重要的資料,用來告訴瀏覽器儘快下載這些資源,並且要搭配as
來使用。
<link rel="preload" as="script" href="critical.js">
<link rel="preload" as="style" href="critical.css">
prefetch:預先猜測哪些 link 會需要下載,所以提前下載該 link 資料,在未來使用到該資料時就會被馬上載入,節省下載時間(prefetch 的優先度低,所以用在比較優先度低的資料)
preconnect: 預先建立好連線(ex, DNS 請求域名 => TCP handshake => server),減少等待連線得時間
Resources: https://juejin.cn/post/7117142442926686215#heading-10
使用合適的圖片格式
第二個圖片優化的方法就是去看我們使用的我們使用的圖片格式是什麼,然後看能不能透過更改格式的方式來達到圖片的優化。首先我們先來介紹常見的圖片格式,圖片格式可以分成兩類,一種是 Vector graphics(向量圖檔),另外一種則是 Raster graphics(點陣圖檔)。Raster graphics 的優點是他的色彩顯示畫質很精細,但是他在放大時畫面會變模糊,常見的 Vector graphics 包含 GIF、JPEG、PNG,而 Vector graphics 的優點是它在放大縮小時都會保持一樣的銳利度,而且他的檔案大小非常小,缺點是其不適合用在色彩鮮豔的圖片。常見的 Vector graphics 有 SVG。
常見格式 | 優點 | 缺點 | |
---|---|---|---|
Vector graphics | SVG | 1. 可擴展性,代表檔案不管放大或是縮小都會保持一樣的銳利度。2. 檔案小 3. 適合用在圖案是簡單幾何圖形或是文字。4. 以上幾點,適用用在小的圖片上,像是用在網頁的 logo 上 | 不適合用在顏色鮮豔、圖案複雜的照片 |
Raster graphics | GIF, JPEG, PNG | 色彩顯示更精細 | 放大時,畫面會變模糊 |
通常前端在處理圖片時,很多時候是在處理 GIF、JPEG、PNG 等等格式的圖檔,這裡我們就這幾種來優缺利弊分析一下,這樣我們下次前端處理圖檔時,就可以把耗費資源的圖片格式改成檔案較小的格式來優化 LCP 摟!
支援度 | 檔案大小 | 畫面 | |
---|---|---|---|
PNG | 高 | 大 | 支援透明度,不失真壓縮所以畫面品質高 |
JPEG | 高 | 中 | 不支援透明度,使用失真壓縮所以導致畫面品質降低 |
WebP | 主流瀏覽器支援 | 小 | 支援透明度,畫面品質高 |
AVIF | 少數瀏覽器支援 | 小 | 支援透明度,畫面品質高 |
如果在使用 webp 時遇到瀏覽器不資源的情況,可以使用picture
搭配img
來在不同的瀏覽器中顯示其所資源的圖片格式
<picture>
<source srcset="/images/cereal-box.webp" type="image/webp" />
<source srcset="/images/cereal-box.jp2" type="image/jp2" />
<img src="/images/cereal-box.jxr" type="image/vnd.ms-photo" />
</picture>
這樣在遇到不資源 webp 的瀏覽器時,就會接續往下找下一個檔案(ex, jp2 格式)能否資源該瀏覽器。
接下來我們會介紹用 CDN 的方式來優化 image
image CDN
Image CDN 是一種網路服務,它主要的功能是圖片的轉換與優化的服務,我們預先把照片儲存在我們自己架設或是供應方提供的 server 裡,然後只要在需要用到的時候再去 call api 去拿這個照片就好了!
透過從 CDN 存取圖片的方式,我們可以不用在本地端儲存圖片,來減少前端檔案的大小,進而讓網頁可以跑更快!
使用 image CDN 的方法
- 自己架設 image CDN,透過 thumbor
- Image CDN 服務提供者,常見的包含 cloudinary、cloudflare等
線上壓縮圖片
最後一個我們介紹來優化圖片的方法是線上圖片壓縮器!做法是先透過線上圖片壓縮器把圖片檔案壓縮過後,再把他存到程式碼裡! 我推薦以下這兩個壓縮網站。
https://compressor.io/ https://tinypng.com/
額外補充 image 常見的問題
- 如何作出響應式 image
推薦閱讀文章:
https://elad.medium.com/a-complete-guide-for-responsive-images-b13db359c6c7
- 怎麼選擇常見 image 總類( img tag vs background-image )
TL;DR 如果圖片是屬於網站內容的一部分,使用 image 加上 alt tag,舉例像是網站的名稱頭像。 反之,用 background-image。
推薦閱讀文章:
https://stackoverflow.com/questions/492809/when-to-use-img-vs-css-background-image/492834#492834
img 響應式
- 用
srcset
來做響應式 image
這裡推薦一個很棒的srcset
教學
- 手寫 function,在不同視窗大小載入不同大小的 image
缺點:要 re-render 才能在轉化畫面大小的時候更換圖片
function responsiveImage(image1x, image2x, image3x) {
const windowWidth = window.innerWidth;
switch (windowWidth) {
case windowWidth >= 1800:
return image3x;
case windowWidth >= 1440:
return image2x;
case windowWidth >= 768:
return image1x;
default:
return image1x;
}
}
- backgroundImage 的話可以使用 image-set
缺點: 目前只能用 device pixel ratio 的方式來轉換圖片,目前不支援 width。代表會根據 device 的 device pixel ratio 來決定 https://developer.mozilla.org/en-US/docs/Web/CSS/image/image-set
device pixel ratio 介紹:
https://web.dev/codelab-density-descriptors/
- 圖片很大跑不出來,或是間隔很久才跑出來?
除了上面幾個讓圖片縮小的方法,也可以透過 progressive image 來增加使用者的體驗。progressive image 的想法是先載入一個檔案比較小的同一個 image,然後再載入大的 image,這樣使用者就不會有很長的沒有圖片的空檔,下面推薦一個不錯的學習資源。
額外補充:
lazy loading image 時使用 placeholder image 的方法:
面試題:
- 圖片優化方法?
- 圖片在 loading 很慢跑不出來的時候要怎麼處理?
https://www.cythilya.tw/2018/08/24/responsive-images/ https://web.dev/optimize-vitals-lighthouse/ https://juejin.cn/post/6844904024165056525