- 原文地址:Front-End Performance Checklist 2019 — 3
- 原文作者:Vitaly Friedman
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:Starrier
- 校對者:kikooo,Jingyuan0000
2019 前端效能優化年度總結 — 第三部分
讓 2019 來得更迅速吧~你正在閱讀的是 2019 年前端效能優化年度總結,始於 2016。
[譯] 2019 前端效能優化年度總結 — 第一部分
[譯] 2019 前端效能優化年度總結 — 第二部分
[譯] 2019 前端效能優化年度總結 — 第三部分
[譯] 2019 前端效能優化年度總結 — 第四部分
[譯] 2019 前端效能優化年度總結 — 第五部分
[譯] 2019 前端效能優化年度總結 — 第六部分
目錄
資源優化
17. 使用 Brotli 或 Zopfli 來對純文字進行壓縮
2015 年,Google 推出了 Brotli,一種新開源的無損資料格式,現已被所有現代瀏覽器所支援。實際上,Brotli 比 Gzip 和 Deflate 有效得多。因為它比較依賴配置,所以這種壓縮可能會(非常)慢,但較慢的壓縮意味著更高的壓縮率。不過它解壓速度很快。所以你可以考慮 Brotli 為你的網站所節省的成本。
只有使用者通過 HTTPS 訪問站點時,瀏覽器才會接受這種格式。那代價是什麼呢?Brotli 並沒有預安裝在一些伺服器上,所以如果沒有自編譯 Nginx,那麼配置就會相對困難。儘管如此,它也並非是不可攻破的難題,比如,Apache 自 2.4.26 版本起,開始逐步對它進行支援。得益於 Brotli 被眾多廠商支援,許多 CDN 也開始支援它(Akamai、AWS、KeyCDN、Fastly、Cloudlare、CDN77),你甚至(結合 service worker 一起使用)可以在不支援它的 CDN 上,啟用 Brotli。
在最高階別壓縮時,Brotli 會非常緩慢,以至於伺服器在開始傳送響應前等待動態壓縮資源所花費的時間,可能會抵消檔案大小(被壓縮後)的潛在增益。但對於靜態壓縮,應該首選更高階別的壓縮。
或者,你可以考慮使用將資料編碼為 Deflate、Gzip 和 Zlib 格式的 Zopfli 的壓縮演算法。任何普通的 Gzip 壓縮資源都可以通過 Zopfli 改進的 Deflate 編碼達到比 Zlib 的最大壓縮率小 3% 到 8%的檔案大小。問題是壓縮檔案大約需要耗費 80 倍的時間。這就是為什麼在資源上使用 Zopfli 是個好主意,因為這些資源不會發生太大的變化,它們被設計成只壓縮一次但可以下載多次。
如果可以降低動態壓縮靜態資源的成本,那麼這種付出是值得的。Brotli 和 Zopfli 都可以用於任意純文字的有效負載 —— HTML、CSS、SVG、JavaScript 等。
有何對策呢?使用最高階別的 Brotli + Gzip 來預壓縮靜態資源,使用 Brotli 在 1 — 4 級中動態壓縮(動態)HTML。確保伺服器正確處理 Brotli 或 Gzip 的協議內容。如果你在伺服器上無法安裝/維護 Brotli,請使用 Zopfli。
18. 使用響應影像和 WebP
儘量使用帶有 srcset
、sizes
屬性的響應式圖片和 <picture>
元素響應式圖片。當然,你還可以通過在原生 <picture>
上使用 WebP圖片以及回退到 JPEG 的機制或者使用協議內容的方式中使用 WebP 格式 (在 Chrome、Opera、Firefox 65、Edge 18 中都被支援的格式)(參見 Andreas Bovens 的程式碼片段),或者使用協議內容(Accept
頭部)。Ire Aderinokun 也有關於將影像轉換為 WebP 影像的超詳細教程。
原生 Sketch 是支援 WebP 的,可以使用 Phtotshop 的 WebP 外掛從 Photoshop 中匯出 WebP 影像。當然也存在其他可用的選項。如果你正在使用 WordPress 或 Joomla,也可以使用一些擴充套件來幫助你自己輕鬆實現對 WebP 的支援,比如適用於 WordPress 的 Optimus 和 Cache Enabler,Joomla 當然也存在對應可提供支援的擴充套件 (通過使用 Cody Arsenault)。
需要注意的是,儘管 WebP 影像檔案大小等價於 Guetzli 和 Zopfli,但它並不支援像 JPEG 這樣的漸進式渲染,這也是使用者以前通過 JPEG 可以更快地看到實際影像的原因,儘管 WebP 影像在網路中的傳輸速度更快。使用 JPEG,我們可以將一半甚至四分之一的資料提供給使用者,然後再載入剩餘資料,而不是像 WebP 那樣可能會導致有不完整的影像。你應該根據自己的需求來進行取捨:使用 WebP,你可以有效減少負載,使用 JPEG,你可以提高效能感知。
在 Smashing Magazine 中,我們使用 -opt
字尾來為影像命名 —— 比如,brotli-compression-opt.png
;這樣,當我們發現影像包含該字尾時,團隊成員就會明白這個影像已經被優化過了。—— 難以置信!—— Jeremy Wagner 出了一本關於 WebP 的書,寫的很好。
響應式圖片端點生成器會自動生成影像和標記。
19. 影像的優化是否得當?
當你在開發 landing page 時,特定影像的載入必須很快,要確保 JPEG 是漸進載入的並且經過了 [mozJPEG] 或者 Guetzli 的壓縮(通過操作掃描級別來改進開始渲染的時間),Google 新開源的編碼器專注於效能感知,並利用了從 Zopfli 和 WebP 中所學的優點。唯一的缺點是:處理時間慢(每百萬畫素需要一分鐘的 CPU)。對於 PNG 來說,我們可以使用 Pingo,對於 SVG 來說,我們可以使用 SVGO 或 SVGOMG。如果你需要快速預覽、複製或下載網站上的所有 SVG 資源,那麼你可以嘗試使用 svg-grabber 。
雖然每一篇影像優化文章都會說,但是我還是要提醒應該保證向量資源的乾淨和緊湊。要記得清理未使用的資源,刪除不必要的後設資料以及圖稿中的路徑點數量(比如 SVG 這類程式碼)(感謝 Jeremy!)
還有更高階的選項,比如:
-
使用 Squoosh 以最佳壓縮級別(有損或無損)壓縮。調整和操作影像。
-
使用響應式影像斷點生成器或 Cloudinary、Imgix 這樣的服務來實現自動化影像優化。此外,在許多情況下,使用
srcset
和sizes
可以獲得最佳效果。 -
要檢查響應標記的效率,你可以使用 imaging-heap(一個命令列工具)來檢測不同視窗大小和裝置畫素比的效果。
-
使用 lazysizes 來延遲載入影像和 iframes,這是一個通過檢測使用者互動(或之後我們將討論的 IntersectionObserver)來觸發任何可見性修改的庫。
-
注意預設載入的影像,它們可能永遠也用不到 —— 例如,在 carousels、accordions 和 image galleries。
-
考慮根據請求型別來指定的不同影像顯示以通過 Sizes 屬性切換影像,比如,操作
sizes
來交換 magnifier 元件中的資料來源。 -
為防止前景和背景影像的意外下載,請檢查影像下載的不一致性。
-
為了從根本上優化儲存,你可以使用 Dropbox 的新格式(Lepton)來對 JPEG 執行平均值可達到 22% 的無失真壓縮。
-
注意 CSS 屬性中的
aspect-ratio
屬性 和intrinsicsize
屬性,它們允許為影像設定寬高和尺寸,因此瀏覽器為了避免樣式錯亂,可以在頁面載入期間提前預留一個預定義的佈局槽。 -
如果你喜歡冒險,為了更快地通過網路傳輸影像,可以使用基於 CDN 的實時過濾器 Edge workers 來終止並重排 HTTP/2 流。Edge workers 使用你可以控制的 JavaScript 流模組(它們是執行在 CDN 上的,可以修改響應流),這樣你就可以控制影像的傳輸。相對於 service worker 來說,這個過程時間稍長,因為你無法控制傳輸過程,但它確實適用於 Edge workers。因此,你可以在針對特定登入頁面逐步儲存的靜態 JPEG 上使用它們。
imaging-heap(一個用於檢測跨視窗大小及裝置畫素比的載入效率的命令列工具)的輸出樣例,(影像來源) (詳細預覽)
響應式影像的未來可能會隨著採用客戶端提示而發生鉅變。客戶端提示內容是 HTTP 的請求頭欄位,例如 DPR
、Viewport-Width
、Width
、Save-Data
、Accept
(指定影像格式首選項)等。它們應該告知伺服器使用者的瀏覽器、螢幕、連線等細節。因此,伺服器可以決定如何用對應大小的影像來填充佈局,而且只提供對應格式所需的影像。通過客戶端提示,我們將資源從 HTML 標記中,遷移到客戶端和伺服器之間的請求響應協議中。
就像 Ilya Grigorik 說的那樣,客戶端提示使影像處理更加完整 —— 它們不是響應式影像的替代品。<picture>
在 HTML 標記中提供了必要藝術方向的控制。客戶端提示為請求的影像提供註釋來實現資源選擇的自動化。Service Worker 為客戶端提供完整的請求和響應管理功能。比如,Service Worker 可以在請求中附加新的客戶端提示 header 值,重寫 URL 並將影像請求指向 CDN,根據連結調整響應,使用者偏好等。它不僅適用於影像資源,也適用於所有其他請求。
對於支援客戶端提示的客戶端,可以檢測到在影像上已經節省了 42% 的位元組和超過 70% 的 1MB+ 位元組數。在 Smashing 雜誌上,我們同樣可以檢測到已經提高了 19-32% 的效能。不幸的是,客戶端提示仍然需要得到瀏覽器的支援才行。Firefox 和 Edge 正在考慮對它的支援。但如果同時提供普通的響應影像標記和客戶端提示的 <meta>
標記,瀏覽器將評估響應影像標記並使用客戶端提示 HTTP header 請求相應的影像。
還不夠?那麼你可以使用多種背景影像技術來提高影像的感知效能。請記住,處理對比以及模糊不必要細節(或刪除顏色)也可以減小檔案大小。你想放大一張小照片而不至於損失質量的話,可以考慮使用 Letsenhance.io。
到目前為止,這些優化只涉及基本內容。Addy Osmani 出版了一份非常詳細的關於基本影像優化的指南,這份指南對於影像壓縮和顏色管理的細節有很深入的講解。例如,你可以模糊影像中不必要的部分(通過應用高斯模糊過濾器)來減小檔案大小,甚至可以移除顏色或將影像轉換為黑白來進一步縮小檔案。對於背景影像,從 Photoshop 中匯出的照片質量只有 0 到 10% 是完全可以接受的。不要在 web 上使用 JPEG-XR —— “在 CPU 上解碼 JPEG-XRs 軟體端這個過程會讓節省位元組大小這個潛在地積極影響失效,甚至更糟,尤其是在 SPAs 情況下”。
20. 視訊優化是否得當?
到目前為止,我們的已經討論完了影像的相關內容,但我們避免了關於 GIF 優點的探討。坦白說,與其載入影響渲染效能和頻寬的重動畫 GIF,不如選擇動態 WebP(GIF 作為回退)或者用 HTML5 videos 迴圈來替換它們。是的,帶有 <video>
的瀏覽器效能極差,而且與影像不同的是,瀏覽器不會預載入 <video>
內容,但它們往往比 GIF 更輕量級、更小。別無他法了麼?那麼至少我們可以通過 Lossy GIF、gifsicle 或 giflossy 來有失真壓縮 GIF。
早期測試表明帶有 img
標籤的內聯視訊相較與等效的 GIF,除了檔案大小問題外,前者的顯示的速度要快 20 倍,解碼要快 7 倍。雖然在 Safari 技術預覽中宣告瞭對 <img src=".mp4">
的技術支援,但是這個特性還遠未普及,因此它在近期內不會被採用。
Addy Osmani 推薦用迴圈內聯視訊來取代 GIF 動畫。檔案大小差異明顯(節省了 80%)。(預覽)
前端是不停進步的領域,多年來,視訊格式一直在不停改革。很長一段時間裡,我們一直希望 WebM 可以成為格式的統治者,而 WebP(基本上是 WebM 視訊容器中的一個靜止影像)將取代過時的影像格式。儘管這些年來 WebP 和 WebM 獲得了支援,但我們所希望看到的突破並未發生。
在 2018,Alliance of Open Media 釋出了一種名為 AV1 的視訊格式。AV1 具有和 H.265(H.264 的改進版本)編碼器類似的壓縮,但與後者不同的是,AV1 是免費的。H.265 的許可證價格迫使瀏覽器供應商採用效能相同的 AV1:AV1(與 H.265 一樣)的壓縮效能是 WebP 的兩倍。
AV1 很有可能成為網路視訊的終極標準。(影像來源:Wikimedia.org) (詳細預覽)
事實上,目前 Apple 使用的是 HEIF 格式和 HEVC (H.265),最新的 IOS 中,所有的照片和視訊都以這些格式儲存,而不是純 JPEG 格式。儘管 HEIF 和 HEVC (H.265) 並沒有在網上被公開使用,但被瀏覽器已經開始對慢慢支援 AV1 了。因此在你的 <video>
標籤中可以新增 AV1
,因為所有的瀏覽器供應商都會慢慢加入對它的支援。
目前來說,使用最廣泛的是 H.264,由 MP4 檔案提供服務,因此在提供檔案之前,請確保你的 MP4 檔案用 multipass-encoding 處理過,用 frei0r iirblur 進行了模糊處理(如果適用),moov atom metadata 也被移動到檔案頭部,而你的伺服器接受位元組服務。Boris Schapira 提供了 FFmpeg 的確切說明來最大限度地優化視訊。當然,提供 WebM 格式作為替代方案也會有所幫助。
視訊回放效能本身就有很多內容可以研究,如果你想深入瞭解它的細節,可以參閱 Doug Sillar 關於當前視訊現狀和視訊傳輸最佳實踐的系列視訊。包括視訊傳輸指標、視訊預載入、壓縮和流媒體等詳細資訊。
Zach Leatherman 的字型載入策略綜合指南為 web 字型傳輸提供了十幾種選擇。
21. Web 字型優化過了麼?
值得提出的第一個問題就是,你是否可以首選 UI 系統字型。如果不是上述情況,那你所提供的 Web 字型很有可能包括系統字型沒有使用的字形或額外的特性或者字型粗細。你可以要求字型提供方將字型分組,或者如果你使用的是開源字型,你可以使用 Glyphhanger 或 Fontsquirrel 自行對它們進行子集化。你甚至可以使用 Peter Müller 的 subfont,一個可以自動化你整個流程的命令列工具,它可以靜態分析你的頁面,生成最佳 Web 字型子集,然後注入頁面中。
WOFF2 的支援性是最好的,你可以使用 WOFF 作為不支援 WOFF2 的瀏覽器的備用選項 —— 畢竟,系統字型對遺留的瀏覽器版本會更友好。Web 字型的載入有很多,很多,很多的選項。你可以從 Zach Leatherman 的 “字型載入策略綜合指南“中選擇一種策略(程式碼片段也可以在 Web 字型載入中找到)。
現在,更好的選項應該是使用 Critical FOFT 結合 preload
和 “The Compromise” 方法。它們都使用兩階段渲染來逐步提供 Web 字型 —— 首先是使用 Web 字型快速準確地渲染頁面所需的小超集,然後再非同步載入剩餘部分,不同的是 “The Compromise” 技術只在字型載入事件不受支援的的情況下才非同步載入 polyfill,所以預設情況下不需要載入 polyfill。需要快速入門?Zach Leatherman 有一個 快速入門的 23 分鐘教程和案例研究來幫助你使用字型。
一般而言,使用 preload
資源提示來預載入字型是個好主意,但需要在你的標記中包含 CSS 和 JavaScript 的連結。否則,字型載入會在第一次渲染時消耗時間。儘管如此,有選擇性地選擇重要檔案是個好主意。比如,渲染至關重要的檔案會有助於你避免視覺化和具有破壞性的文字重新整理檔案。總之,Zach 建議預載入每個系列的一到兩個字型。如果這些字型不是很關鍵的話,延遲載入一些字型也是有意義的。
沒有人喜歡等待內容的顯示。使用 font-display
CSS 描述符,我們可以控制字型載入行為並使內容可被立即讀取(font-display: optional
),或者幾乎是立即被讀(font-display: swap
)。然而,如果你想避免文字被重排,我們仍然需要使用字型載入 API,尤其是 group repaints,或者當你使用第三方主機時。除非你可以 用 Cloudflare workers 的 Google 字型。討論 Google 字型:考慮使用 google-webfonts-helper,這是一種輕鬆自我託管 Google 字型的方式。如果可以,那麼自行託管你的字型會賦予你對字型最大程度的控制。
一般而言,如果你選擇 font-display: optional
,那麼就需要放棄使用 preload
,因為它會提前觸發對 Web 字型的請求(如果你有其他需要獲取的關鍵路徑資源,就會導致網路阻塞)。preconnect
可以更快地獲取跨域字型請求,但要謹慎使用 preload
,因為來自不同域的預載入字型會導致網路競爭。所有這些技術都包含在 Zach 的 Web 字型載入。
此外,如果使用者在輔助功能首選項中啟用了 Reduce Motion 或選擇資料保護模式(詳細內容可參閱 Save-Data
header),那麼最好是選擇不使用 Web 字型(至少是第二階段的渲染中)。或者當使用者碰巧連結速度較慢時(通過 網路資訊 API)。
要檢測 Web 字型的載入效能,可以考慮使用所有文字視覺化的度量標準(字型載入的時,所有內容立即以 Web 字型顯示),以及首次渲染後的 Web 字型重排計數。顯然,這兩種指標越低,效能越好。重要的是考慮到變數字型對效能的需求。它們為設計師提供了更大的字型選擇空間,代價是單個序列請求與許多單獨的檔案請求相反。這個單一的請求可能會緩慢地阻止頁面上的整個排版外觀。不過,好的一面是,在使用可變字型的情況下,預設情況下我們將得到一個重新的檔案流,因此不需要 JavaScript 對重新繪製的內容進行分組。
有沒有一種完美的 Web 字型載入策略? 子集字型為二階段渲染做好準備,使用 font-display
描述符來宣告它們,使用字型載入 API 對重新繪製的內容進行分組並將字型儲存在持久化的 service worker 快取中。如果有必要,你可以回到 Bram Stein 的 Font Face Observer。如果你有興趣檢測字型載入的效能,Andreas Marschke 研究了使用 字型 API 和 UserTiming API 的效能。
最後,不要忘記加入 unicode-range
,將一個大字型分解成更小的特定語言字型,使用 Monica Dinculescu 的 font-style-matcher 來最小化佈局上的不和諧變化,這是因為回退和 Web 字型之間的大小會產生不一致。
[譯] 2019 前端效能優化年度總結 — 第一部分
[譯] 2019 前端效能優化年度總結 — 第二部分
[譯] 2019 前端效能優化年度總結 — 第三部分
[譯] 2019 前端效能優化年度總結 — 第四部分
[譯] 2019 前端效能優化年度總結 — 第五部分
[譯] 2019 前端效能優化年度總結 — 第六部分
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。