2018 前端性能優化清單 - 第 3 部分

下面你將會看到你可能須要考慮到的前端性能優化問題,以保證你的應用具備快速和流暢的響應時間。css


靜態資源優化

  1. 你是使用 Brotli 仍是 Zopfli 進行純文本壓縮?

在 2005 年,Google 推出了 Brotli,一個新的開源無損數據壓縮格式,如今 被全部的現代瀏覽器所支持。實際上,Brotli 比 Gzip 和 Deflate 更有效。取決於設置信息,壓縮可能會很是慢。可是緩慢的壓縮過程會提升壓縮率,而且仍然能夠快速解壓。固然,解壓縮速度很快。html

只有當用戶經過 HTTPS 訪問網站時,瀏覽器纔會採用。Brotli 如今還不能預裝在某些服務器上,並且若是不本身構建 NGINX 和 UBUNTU 的話很難部署。不過這也並不難。實際上,一些 CDN 是支持的,甚至 能夠也能夠經過服務器在不支持 CDN 的狀況下啓用 Brotli前端

在最高級別的壓縮下,Brotli 的速度會變得很是慢,以致於服務器在等待動態壓縮資源時開始發送響應所花費的時間可能會使文件大小的任何潛在收益都無效。可是,對於靜態壓縮,高壓縮比的設置比較受歡迎 —— (感謝 Jeremy!android

或者,你能夠考慮使用 Zopfli 的壓縮算法,將數據編碼爲 Deflate,Gzip 和 Zlib 格式。Zopfli 改進的 Deflate 編碼使得任何使用 Gzip 壓縮的文件受益,由於這些文件大小比 用Zlib 最強壓縮後還要小 3% 到 8%。問題在於壓縮文件的時間是原來的大約 80倍。這就是爲何雖然 使用 Zopfli 是一個好主意可是變化並不大,文件都須要設計爲只壓縮一次能夠屢次下載的。ios

比較好的方法是你能夠繞過動態壓縮靜態資源的成本。Brotli 和 Zopfli 均可以用於明文傳輸 —— HTML,CSS,SVG,JavaScript 等。git

有什麼方法呢?在最高等級和 Brotli 的 1-4 級動態壓縮 HTML 使用 Brotli+Gzip 預壓縮靜態資源。同時,檢查 Brotli 是否支持 CDN,(例如 KeyCDN,CDN77,Fastly)。確保服務器可以使用 Brotli 或 gzip 處理內容。若是你不能安裝或者維護服務器上的 Brotli,那麼請使用 Zopfli。github

  1. 圖像是否進行了適當的優化? 儘量經過 srcsetsizes<picture> 元素使用 響應式圖片。也能夠經過 <picture> 元素使用 WebP 格式的圖像(Chrom,Opera,Firefox soon支持),或者一個 JPEG 的回調(見 Andreas Bovens 的 code snippet)或者經過使用內容協商(使用 Accept 頭信息)。

Sketch 自己就支持 WebP 而且 WebP 圖像能夠經過使用 WebP 插件 從 PhotoShop 中導出。也有其餘選擇可使用,若是你使用 WordPress 或者 Joomla,也有能夠輕鬆支持 WebP 的擴展,例如 OptimusCache Enabler(經過 Cody Arsenaultweb

你能夠仍然使用 client hints,但仍須要得到一些瀏覽器支持。沒有足夠的資源支持響應式圖片?使用 斷點發生器 或者相似 Cloudinary 這樣的服務自動優化圖片。一樣,在許多狀況下,只使用 srcsetsizes 會有不錯的效果。算法

On Smashing Magazine, we use the postfix -opt for image names — for example, brotli-compression-opt.png; whenever an image contains that postfix, everybody on the team knows that the image has already been optimized.chrome

響應圖像斷點發生器

響應圖像斷點生成器自動生成圖像和標記生成。

  1. 將圖像優化到下一個級別 如今有一個相當重要着陸頁,有一個特定的圖片的加載速度很是關鍵,確保 JPEGs 是漸進式的而且使用 AdeptmozJPEG (經過操縱掃描級來改善開始渲染時間)或者 Guetzli 壓縮,谷歌新的開源編碼器重點是可以感官的性能,並借鑑 Zopfli 和 WebP。惟一的 不足 是:處理的時間慢(每百萬像素 CPU 一分鐘)。至於 png,咱們可使用 Pingo,和 svgo,對於 SVG 的處理,咱們使用 SVGOSVGOMG

每個圖像優化的文章會說明,但始終保持保持矢量資產清潔老是值得提醒的。確保清理未使用的資源,刪除沒必要要的元數據,並減小圖稿中的路徑點數量(從而減小SVG代碼)。(感謝,Jeremy!

到目前爲止,這些優化只涵蓋了基礎知識。 Addy Osmani 已經發布了 一個很是詳細的基本圖像優化指南,深刻到圖像壓縮和顏色管理的細節。 例如,您能夠模糊圖像中沒必要要的部分(經過對其應用高斯模糊濾鏡)以減少文件大小,最終甚至能夠開始移除顏色或將圖像變成黑白色,以進一步縮小圖像尺寸。 對於背景圖像, 從Photoshop 導出的照片質量爲 0 到 10% 也是絕對能夠接受的。

那麼 GIF 圖片呢?咱們可使用 循環的 HTML5 視頻,而不是影響渲染性能和帶寬的重度 GIF 動畫,而使用循環的 HTML5 視頻,<video> 會使得 瀏覽器的性能很慢,並且與圖像不一樣的是,瀏覽器不會預先加載 <video> 內容。 至少咱們可使用 Lossy GIF, gifsicle 或者 giflossy 添加有損壓縮 GIF。

消息: 但願不久之後咱們可使用 <img src=".mp4"> 來加載視頻, 早期的測試代表 img 標籤比同等大小的 GIF 顯示的要 快 20 多倍解析速度與要快 7 倍多

還不夠好?那麼,你也可使用 多種 背景 圖像 技術 提升圖像的感知性能。 記着,減小對比度 和模糊沒必要要的細節(或消除顏色)也能夠減少文件的大小。 你須要放大一個小照片而不失真?考慮使用 Letsenhance.io

Zach Leatherman的字體加載策略綜合指南

Zach Leatherman 的 字體加載策略綜合指南 提供了十幾種更好的網頁字體發送選項

  1. Web字體是否優化? 首先須要問一個問題,你是否能不使用 UI 系統字體。 若是不能夠,那麼你有很大可能使用 Web 網絡字體,會包含字形和額外的功能以及用不到的加粗。 若是您使用的是開源字體(例如,經過僅包含帶有某些特殊的重音字形的拉丁語),則能夠只選擇部分 Web 字體來減小其文件大小。

WOFF2 很是好,你可使用 WOFF 和 OTF 做爲不支持它的瀏覽器的備選。另外,從 Zach Leatherman 的《字體加載策略綜合指南》(代碼片斷也能夠做爲 Web字體加載片斷)中選擇一種策略,並使用服務器緩存持久地緩存字體。是否是感受小有成就?Pixel Ambacht 有一個 快速教程和案例研究,讓你的字體按順序排列。

若是你沒法從你的服務器拿到字體並依賴於第三方主機,請確保使用 字體加載事件(或對不支持它的瀏覽器使用 Web字體加載器FOUT 要優於 FOIT; 當即開始渲染文本,並異步加載字體 —— 也可使用 loadCSS。 你也能夠 擺脫本地安裝的操做系統字體,也可使用 可變的 字體

怎麼才能是一個無漏洞的字體加載策略? 從 font-display 開始,而後回到 Font Loading API,而後回到 Bram Stein 的 Font Face Observer感謝 Jeremy!)若是你有興趣從用戶的角度來衡量字體加載的性能, Andreas Marschke 探索了 使用 Font API 和 UserTiming API 進行性能跟蹤

此外,不要忘記包含 font-display:optional 描述符來提供彈性和快速的字體回退,unicode-range 將大字體分解成更小的語言特定的字體,以及Monica Dinculescu 的字體樣式匹配器 用來解決因爲兩種字體之間的大小差別,最大限度地減小了佈局上的震動的問題。

交付優化

  1. 你是否異步加載 JavaScript? 當用戶請求頁面時,瀏覽器獲取 HTML 並構造 DOM,而後獲取 CSS 並構造 CSSOM,而後經過匹配 DOM 和 CSSOM 生成一個渲染樹。若是有任何的 JavaScript 須要解決,瀏覽器將不會開始渲染頁面,直到 JavaScript 解決完畢,這樣就會延遲渲染。 做爲開發人員,咱們必須明確告訴瀏覽器不要等待並當即開始渲染頁面。 爲腳本執行此操做的方法是使用 HTML 中的 deferasync 屬性。

事實證實,咱們 應該把 defer 改成 async(由於 ie9 及如下不支持 async)。 另外,如上所述,限制第三方庫和腳本的影響,特別是使用社交共享按鈕和嵌入的 <iframe> 嵌入(如地圖)。 大小限制 有助於防止 JavaScript 庫過大:若是您不當心添加了大量依賴項,該工具將通知你並拋出錯誤。 您可使用 靜態社交分享按鈕(如經過 SSBG )和 靜態連接 來代替交互式地圖。

  1. 你是否懶加載了開銷很大並使用 Intersection Observer 的代碼? 若是您須要延遲加載圖片、視頻、廣告腳本、A/B 測試腳本或任何其餘資源,則可使用 Intersection Observer API,它提供了一種方法異步觀察目標元素與 祖先元素或頂層文檔的視口。基本上,你須要建立一個新的 IntersectionObserver 對象,它接收一個回調函數和一組選項。 而後咱們添加一個目標來觀察。

當目標變得可見或不可見時執行回調函數,因此當它攔截視口時,能夠在元素變得可見以前開始採起一些行動。 事實上,咱們能夠精確地控制觀察者的回調什麼時候被調用,使用 rootMargin(根邊緣)和 threshold(一個數字或者一個數字數組來表示目標可見度的百分比, 瞄準)。Alejandro Garcia Anglada 發表了一個 簡單的教程 關於如何實際實施的方便教程。

你甚至能夠經過向你的網頁添加 漸進式圖片加載 來將其提高到新的水平。 與 Facebook,Pinterest 和 Medium 相似,你能夠首先加載低質量或模糊的圖像,而後在頁面繼續加載時,使用 Guy Podjarny 提出的 LQIP (Low Quality Image Placeholders) technique(低質量圖像佔位符)技術替換它們的所有質量版本。

若是技術提升了用戶體驗,觀點就不同了,但它確定會提升第一次有意義的繪畫的時間。咱們甚至能夠經過使用 SQIP 建立圖像的低質量版本做爲 SVG 佔位符來實現自動化。 這些佔位符能夠嵌入 HTML 中,由於它們天然能夠用文本壓縮方法壓縮。 Dean Hume 在他的文章中 描述了 如何使用相交觀測器來實現這種技術。

瀏覽器支持成都如何呢?Decent,與 Chrome,火狐,Edge 和 Samsung Internet 已經支持了。 WebKit 目前 正在開發中。若是瀏覽器不支持呢? 若是不支持交叉點觀察者,咱們仍然能夠 延遲加載 一個 polyfill 或當即加載圖像。甚至還有一個 library

一般,咱們會使用懶加載來處理全部代價較大的組件,如 字體,JavaScript,輪播,視頻和 iframe。 你甚至能夠根據網絡質量調整內容服務。網絡信息 API,特別是 navigator.connection.effectiveType(Chrome 62+)使用 RTT 和下行鏈路值來更準確地表示鏈接和用戶能夠處理的數據。 您可使用它來徹底刪除視頻自動播放,背景圖片或 Web 字體,以便鏈接速度太慢。

  1. 你是否優先加載關鍵的 CSS? 爲確保瀏覽器儘快開始渲染頁面,一般 會收集開始渲染頁面的第一個可見部分所需的全部 CSS(稱爲 「關鍵CSS」 或 「上一層CSS」)並將其內聯添加到頁面的 <head> 中,從而減小往返。 因爲在慢啓動階段交換包的大小有限,因此關鍵 CSS 的預算大約是 14 KB。

若是超出這個範圍,瀏覽器將須要額外往返取得更多樣式。 CriticalCSSCritical 能夠作到這一點。 你可能須要爲你使用的每一個模板執行此操做。 若是可能的話,考慮使用 Filament Group 使用的 條件內聯方法

使用 HTTP/2,關鍵 CSS 能夠存儲在一個單獨的 CSS 文件中,並經過 服務器推送 來傳遞,而不會增大 HTML 的大小。 問題在於,服務器推送是很 麻煩,由於瀏覽器中存在許多問題和競爭條件。 它一直不被支持,並有一些緩存問題(參見 [Hooman Beheshti介紹的文章](Hooman Beheshti's presentation) 114 頁內容)。事實上,這種影響多是 負面的,會使網絡緩衝區膨脹,從而阻止文檔中的真實幀被傳送。 並且,因爲 TCP 啓動緩慢,彷佛服務器推送在熱鏈接上 更加有效

即便使用 HTTP/1,將關鍵 CSS 放在根目錄上的單獨文件中也是有 好處的,有時甚至比緩存和內聯更爲有效。 Chrome 請求這個頁面的時候會再發送一個 HTTP 鏈接到根目錄,從而不須要 TCP 鏈接來獲取這個 CSS(感謝 Philip!

須要注意的一點是:和 preload 不一樣的是,preload 能夠觸發來自任何域的預加載,而你只能從你本身的域或你所受權的域中推送資源。 一旦服務器獲得來自客戶端的第一個請求,就能夠啓動它。 服務器將資源壓入 Push 緩存,並在鏈接終止時被刪除。 可是,因爲能夠在多個選項卡之間重複使用 HTTP/2 鏈接,因此推送的資源也能夠被來自其餘選項卡的請求聲明(感謝 Inian!)。

目前,服務器並無一個簡答的方法得知被推送的資源 是否已經存在於用戶的緩存中,所以每一個用戶的訪問都會繼續推送資源。所以,您可能須要建立一個 緩存監測 HTTP/2 服務器推送機制。若是被提取,您能夠嘗試從緩存中獲取它們,這樣能夠避免再次推送。

但請記住,新的 cache-digest 規範 無需手動創建這樣的 「緩存感知」 的服務器,基本上在 HTTP/2 中聲明的一個新的幀類型就能夠表達該主機的內容。所以,它對於 CDN 也是特別有用的。

對於動態內容,當服務器須要一些時間來生成響應時,瀏覽器沒法發出任何請求,由於它不知道頁面可能引用的任何子資源。 在這種狀況下,咱們能夠預熱鏈接並增長 TCP 擁塞窗口大小,以便未來的請求能夠更快地完成。 並且,全部內聯配置對於服務器推送都是較好的選擇。事實上,Inian Parameshwaran 對 HTTP/2 Push 和 HTTP Preload 進行了比較 深刻的研究,內容很不錯,其中包含了您可能須要的全部細節。服務器究竟是推送仍是不推送呢?你能夠閱讀一下 Colin Bendell 的 Should I Push?

底線:正如 Sam Saccone 所說preload 有利於將資產的開始下載時間更接近初始請求, 而服務器推送是一個完整的 RTT(或 更多,這取決於您的服務器反應時間 —— 若是你有一個服務器能夠防止沒必要要的推送。

你使用 流響應 嗎?經過流,在初始導航請求中呈現的 HTML 能夠充分利用瀏覽器的流式 HTML 解析器。

  1. 你使用流響應嗎? streams 常常被遺忘和忽略,它提供了異步讀取或寫入數據塊的接口,在任何給定的時間內,只有一部分數據可能在內存中可用。 基本上,只要第一個數據塊可用,它們就容許原始請求的頁面開始處理響應,並使用針對流進行優化的解析器逐步顯示內容。

咱們能夠從多個來源建立一個流。例如,您可讓服務器構建一個殼子來自於緩存,內容來自網絡的流,而不是提供一個空的 UI 外殼並讓它填充它。 正如 Jeff Posnick 指出的,若是您的 web 應用程序由 CMS 提供支持的,那麼服務器渲染 HTML 是經過將部分模板拼接在一塊兒來呈現的,該模型將直接轉換爲使用流式響應,而模板邏輯將從服務器複製而不是你的服務器。Jake Archibald 的 The Year of Web Streams 文章重點介紹瞭如何構建它。對於性能的提高是很是明顯的。

流式傳輸整個 HTML 響應的一個重要優勢是,在初始導航請求期間呈現的 HTML 能夠充分利用瀏覽器的流式 HTML 解析器。 在頁面加載以後插入到文檔中的 HTML 塊(與經過 JavaScript 填充的內容同樣常見)沒法利用此優化。

瀏覽器支持程度如何呢? 詳情請看這裏 Chrome 52+、Firefox 5七、Safari 和 Edge 支持此 API 而且服務器已經支持全部的 現代瀏覽器.

  1. 你使用 Save-Data 存儲數據嗎? 特別是在新興市場工做時,你可能須要考慮優化用戶選擇節省數據的體驗。 Save-Data 客戶端提示請求頭 容許咱們和定製爲成本和性能受限的用戶定製應用程序和有效載荷。 實際上,您能夠將 高 DPI 圖像的請求重寫爲低 DPI 圖像,刪除網頁字體和花哨的特效,關閉視頻自動播放,服務器推送,甚至更改提供標記的方式。

該頭部目前僅支持 Chromium,Android 版 Chrome 或 桌面設備上的 Data Saver 擴展。最後,你還可使用 service worker 和 Network Information API 來提供基於網絡類型的低/高分辨率的圖像。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

寫文章能夠得 異步社區 的書!愛讀書的技術人都在異步社區。我想要讀 《Python編程快速上手——讓繁瑣工做自動化》,但願你也可以喜歡。參與寫做換書活動。

相關文章
相關標籤/搜索