[譯] 網絡現狀:性能提高指南

網絡現狀:性能提高指南

互聯網正在爆發式地增加,咱們建立的 Web 平臺也是如此。咱們一般都沒有考慮到用戶網絡的連通性和使用情景。即便是萬維網現狀的一瞥,也能夠看出咱們尚未創建起同理心和對形勢變化的認知,更不用說對性能的考慮了。javascript

那麼,現今的網絡情況是怎樣的呢?php

地球上 74 億人口中,只有 46% 的人可以上網,平均網絡速度爲 7Mb/s。更重要的是,93% 的互聯網用戶都是經過移動設備上網的 —— 不去迎合手持設備是不可原諒的。數據每每比咱們想象中要昂貴得多 —— 購買 500MB 數據的價格在德國要爲此工做 1 個小時,而在巴西須要 13 個小時(更多有趣的統計能夠看看 Ben Schwarz《泡沫破滅:真實的性能》)。css

咱們的網站表現得也不盡如人意 —— 平均體積大概是初版 Doom 遊戲的大小(3MB 左右)(請注意,爲了統計準確度,須要使用中位數,推薦閱讀 Ilya Grigorik《「平均頁面」是一個神話》。中位數統計出的網站體積目前爲 1.4MB)。圖片能夠輕鬆佔用 1.7MB,而 JavaScript 平均爲 400KB。不只僅只有 Web 平臺,本地應用程序也有一樣的問題,你是否遇到過爲了修復某些 bug,不得不下載 200MB 的應用呢?html

技術人員常常會發現本身處於特權地位。擁有新型高端的筆記本、手機和快速的網絡鏈接。咱們很容易忘記,其實並非每一個人都有這樣的條件(實際上只有少部分人而已)。前端

若是咱們只站在本身而不是用戶的角度來構建 web 平臺,那這將致使糟糕的用戶體驗。java

咱們如何經過在設計和開發中考慮性能來作得更好呢?react

資源優化

最能明顯提高性能但未被充分利用的方式是,從瞭解瀏覽器如何分析和處理資源開始。事實證實,當瀏覽器解析和當即肯定資源的優先級時,在資源發現方面表現得很是不錯。下面是關於關鍵請求的解釋。android

若是請求包含用戶視口渲染所需的資源,那該請求就是關鍵請求。webpack

對於大多數網站,關鍵請求能夠是 HTML、必要的 CSS、LOGO、網絡字體,也多是圖片。事實證實,在大多數狀況下,當資源被請求時,許多其餘不相關的(JavaScript、追蹤代碼、廣告等)也被請求了。不過咱們可以經過仔細挑選重要資源,並調整它們的優先級來避免這種狀況發生。ios

經過 <link rel ='preload'>,咱們能夠手動強制設置資源的優先級,來確保所指望的內容按時渲染。這種技術能夠明顯改善「交互時間」指標,從而使最佳用戶體驗成爲可能。

因爲相關資料的缺少,關鍵請求對許多人來講彷佛仍然是一個黑盒子。幸運的是,Ben Schwarz 發表了一篇很是全面且通俗易懂的文章 —— 《關鍵請求》。另外,你也能夠查看 Addy 關於預加載的文章 —— 《Chrome 中的預加載和優先級》

在 Chrome 開發者工具中啓用優先級
在 Chrome 開發者工具中啓用優先級

🛠 要追蹤優先處理請求的效果,你可使用 Lighthouse 性能檢測工具和關鍵請求鏈路評測,或者查看 Chrome 開發者工具網絡標籤下的請求優先級。

📝 通用性能清單

  1. 主動緩存
  2. 啓用壓縮
  3. 優先關鍵資源
  4. 使用 CDN

圖片優化

頁面傳輸的大部分數據一般都是圖片,所以優化圖片能夠帶來很大的性能提高。有許多現有的策略和工具能夠幫助咱們刪除多餘的字節,但首先要問的是:「圖片對於傳達後續的信息和效果相當重要嗎?」。若是能夠移除,不只能夠節省帶寬,還能夠減小請求。

在某些狀況下,咱們能夠經過不一樣的技術來實現一樣的效果。CSS 有不少具備藝術性的屬性,例如陰影、漸變、動畫和形狀,這就容許咱們用具備合適樣式的 DOM 元素來替代圖片。

選擇正確的格式

若是必須使用圖片,那肯定哪一種格式比較合適是很重要的。通常都在矢量圖和柵格圖之間進行選擇:

  • 矢量圖形:與分辨率無關,文件一般比較小。特別適用於 LOGO、圖標和由簡單圖形(點、線、圓和多邊形)組成的圖片。
  • 柵格圖像:表現內容更豐富。適用於照片。

作出上面的決定後,有這樣的幾種格式供咱們選擇:JPEG、GIF、PNG-八、PNG-24 或者最新的格式,例如 WEBP 或 JPEG-XR。既然有這麼多的選擇,那如何確保咱們選擇的正確性呢?如下是找到最佳格式的基本方法:

  • JPEG:色彩豐富的圖片(例如照片)
  • PNG–8:色彩不是很豐富的圖片
  • PNG–24:具備部分透明度的圖片
  • GIF:動畫圖片

Photoshop 在圖片導出時,能夠經過一些設置來對上述格式的圖片進行優化,例如下降質量、減小噪點或者顏色的數量。確保設計師有性能實踐的意識,並經過正確的優化預設來準備合適的圖片。若是你想了解更多關於如何開發圖片的信息,能夠閱讀 Lara Hogan《速度與激情:以網站性能提高用戶體驗》

嘗試新格式

有這樣幾種由瀏覽器廠商開發的新圖片格式:Google 的 WebP,Apple 的 JPEG 2000 和 Microsoft 的 JPEG-XR。

WebP 是最具備競爭力的,支持無損和有損壓縮使得它被普遍應用。無損 WebP 比 PNG 小 26%,比 JPG 小 25-34%。74% 的瀏覽器支持率及降級方案使它能夠安全地被使用,最多可節省 1/3 的傳輸字節。JPG 和 PNG 能夠經過 Photoshop 和其餘圖像處理程序,也可使用命令行(brew install webp)將其轉換爲 WebP。

若是你想探索這些格式之間的視覺差別,我推薦這個在 Github 上不錯的示例

使用工具和算法進行優化

即使使用了高效的圖片格式也須要後續的處理和優化。這一步很重要。

若是你選擇了體積相對較小的 SVG,它們也須要被壓縮。SVGO 是一個命令行工具,能夠經過剝離沒必要要的元數據來快速優化 SVG。另外,若是你喜歡 Web 界面或者因爲操做系統的限制,也可使用 Jake ArchibaldSVGOMG。因爲 SVG 是基於 XML 的格式,因此它也能夠被服務端 GZIP 壓縮。

ImageOptim 是大多數其餘圖片格式的絕佳選擇,它將 pngcrush、pngquant、MozJPEG、Google Zopfli 等一些不錯的工具打包進了一個綜合的開源包裏面。做爲一個 Mac OS 應用程序、命令行界面和 Sketch 插件,ImageOptim 能夠輕鬆地用於現有的工做流中。大多數 ImageOptim 依賴 CLI 均可以在 Linux 或者 Windows 平臺上使用。

若是你傾向於嘗試新興的編碼器,今年早些時候,Google 發佈了 Guetzli —— 一個源於他們對 WebP 和 Zopfli 研究的開源算法。Guetzli 能夠生成比任何其餘可用的壓縮方法少 35% 體積的 JPEG。惟一的缺點是:處理時間慢(每百萬像素的 CPU 時間爲一分鐘)。

選擇工具時,請確保它們能達到預期並適合團隊的工做流。最好能自動化優化,這樣全部圖片都是優化過了的。

響應式圖片

十年前,也許一種分辨率就能知足全部的場景,但隨着時代的變化,響應式網站現今已大相徑庭。這就是爲何咱們必須特別當心地實施咱們精心優化的視覺資源,並確保它們適應各類視口和設備。幸運的是,感謝響應式圖像社區組織,經過 picture 元素和 srcset 屬性(都有 85%+ 的瀏覽器支持率),咱們能夠完美地作到。

srcset 屬性

srcset 在分辨率切換場景中表現得很是不錯 —— 當咱們想根據用戶的屏幕密度和大小顯示圖片時。根據 srcsetsizes 屬性中一些預約義的規則,瀏覽器將會根據視口選擇最佳的圖片進行展現。這種技術能夠節省帶寬和減小請求,特別是對於移動端用戶。

srcset 屬性使用示例
srcset 屬性使用示例

picture 元素

picture 元素和 media 屬性旨在更容易地通往藝術殿堂。經過爲不一樣的條件提供不一樣的來源(經過 media-queries 測試),不管分辨率如何,咱們始終能聚焦在最重要的圖像元素上。

picture 元素使用示例
picture 元素使用示例

📚 閱讀 Jason Grigsby《響應式圖片 101》 能夠全面地瞭解這兩種方式。

使用圖片 CDN

圖片性能的最後一步就是分發了。全部資源均可以從使用 CDN 中受益,但有一些特定的工具是專門針對圖片的,例如 Cloudinary 或者 imgx。使用這些服務的好處遠不止於減小服務器流量,它還能夠顯著減小響應延遲。

CDN 能夠下降重圖片站點提供自適應和高性能圖片的複雜度。他們提供的服務各不相同(價格也不一樣),可是大多數均可以根據設備和瀏覽器進行尺寸調整、裁剪和肯定最合適的格式,甚至更多 —— 壓縮、檢測像素密度、水印、人臉識別和容許後期處理。藉助這些強大的功能和可以將參數附到 URL 中,使得提供以用戶爲中心的圖片變得垂手可得了。

📝 圖片性能清單

  1. 選擇正確的格式
  2. 儘量使用矢量圖
  3. 若是變化不明顯,則下降質量
  4. 嘗試新格式
  5. 使用工具和算法進行優化
  6. 學習 srcset 屬性和 picture 元素
  7. 使用圖片 CDN

優化網絡字體

使用自定義字體的能力是一個很是強大的設計工具。但權利越大,責任就越大。68% 的網站正在使用網絡字體,而這種資源是最大的性能瓶頸之一(很容易平均達到 100KB,這取決於字體的各類形態和數量)。

即便體積不是最重要的問題,但不可見文本閃現(FOIT)是。當網絡字體在加載中或者加載失敗時,就會發生 FOIT,這會致使空白頁面,從而形成內容沒法訪問。這可能值得咱們仔細檢查是否須要網絡字體。若是是這樣,有一些策略能夠幫助咱們減輕對性能的負面影響。

選擇正確的格式

有四種網絡字體格式:EOT、TTF、WOFF 和近期的 WOFF2。TTF 和 WOFF 被普遍使用,擁有超過 90% 的瀏覽器支持率。根據你所針對的支持狀況,使用 WOFF2 可能最安全,併爲老版本瀏覽器降級使用 WOFF。使用 WOFF2 的優勢是一整套自定義的預處理和壓縮算法(如 Brotli)能夠 縮小 30% 的文件大小和改進過的解析性能。

@font-face 中定義網絡字體的來源時,使用 format() 提示來指定應該使用哪一種格式。

若是你正在使用 Google 字體或者 Typekit 字體,他們都實施了一些策略來減輕對性能的影響。Typekit 全部套件如今都支持異步來預防 FOIT,而且容許其 JavaScript 套件代碼的緩存期限延長 10 天(而不是默認的 10 分鐘)。Google 字體能夠根據用戶設備自動提供最小的文件。

字體選擇評測

不管是否自託管,字體的數量、體積和樣式都將明顯影響性能。
理想狀況下,咱們只須要一種包括常規和粗體的字體。若是你不肯定如何選擇字體,能夠參考 Lara Hogan 的《美學與性能》

使用 Unicode-range 子集

Unicode-range 子集容許將大字體分割成較小的集合。這是一個相對先進的策略,但它可能會明顯地減小字體體積,特別是在針對亞洲語言的時候(你知道中文字體的平均字形數是 20,000 嗎?)。第一步是將字體限制爲必要的語言集,例如拉丁語、希臘語或西里爾語。若是網絡字體只是作 LOGO 類的使用,那徹底可使用 Unicode-range 描述符來選擇特定的字符。

Filament Group 發佈的開源命令行工具 glyph hanger 能夠根據文件或 URL 生成須要的字形列表。或者,基於 web 的 Font Squirrel Web Font Generator,它提供高級子集和優化選項。若是使用 Google 字體或者 Typekit,他們在字體選擇界面都提供了語言子集的選擇,這使得肯定基本子集更容易。

創建字體加載策略

字體是阻塞渲染的 —— 由於瀏覽器須要首先建立 DOM 和 CSSOM;網絡字體用於與現有節點相匹配的 CSS 選擇器以前,它都不會被下載。這種行爲顯然延遲了文本的渲染,一般都會致使前面提到的不可見文本閃現(FOIT)。在較慢的網絡和移動設備上,FOIT 則更加明顯。

實施字體加載策略能夠避免用戶沒法訪問內容。一般,無樣式文本閃現(FOUT)是最簡單和最有效的解決方案。

font-display 是一個新的 CSS 屬性,提供了一個不依賴 JavaScript 的解決方案。不幸的是,它只被部分支持(Chrome 和 Opera),Firefox 和 WebKit 目前在開發中。儘管如此,它能夠而且應該與其餘字體加載機制結合使用。

font-display 屬性示例
font-display 屬性示例

幸運的是,Typekit 的網絡字體加載器Bram Stein字體觀察者 能夠幫助咱們管理字體的加載行爲。此外,Zach Leatherman 是網絡字體性能的專家,他發佈的《字體加載策略綜合指南》將幫助你爲你的項目選擇正確的方法。

📝 網絡字體性能清單

  1. 選擇正確的格式
  2. 字體選擇評測
  3. 使用 Unicode-range 子集
  4. 創建字體加載策略

優化 JavaScript

目前,JavaScript 包的平均大小爲 446KB,這使得使其成爲第二大致積類型的資源(僅次於圖片)。

咱們可能沒有意識到,咱們所鍾愛的 JavaScript 隱藏着更加危險的性能瓶頸。

監控 JavaScript 傳輸

優化傳輸只是抗衡頁面臃腫的一種方法。JavaScript 下載後,必須由瀏覽器進行解析、編譯和運行。瀏覽一些熱門的網站,咱們會發現,gzip 壓縮後的 JS 在解壓以後至少變大三倍。實際上,咱們正在發送一大堆代碼。

1MB JavaScript 在不一樣的設備上的解析時間。圖片來源於 Addy Osmani 的《JavaScript 啓動性能》

分析解析和編譯時間,對於理解應用程序什麼時候準備好進行交互相當重要,這些時間因用戶設備的硬件能力而異。解析和編譯的時間會很容易地在低端手機上高出 2-5 倍Addy 的研究代表,一個應用程序在普通手機上須要 16 秒才能達到可交互狀態,而在桌面上是 8 秒
分析這些指標相當重要,幸運的是,咱們能夠經過 Chrome 開發者工具來完成。

在 Chrome 開發者工具中審查解析和編譯過程
在 Chrome 開發者工具中審查解析和編譯過程

請務必閱讀 Addy Osmani 在《JavaScript 啓動性能》文中的詳細總結。

移除沒必要要的依賴

現今的包管理方式能夠很容易地隱藏依賴包的數量和大小。webpack-bundle-analyzerbundle-buddy 是很好的可視化工具,能夠幫助咱們識別出重複代碼、最大的性能瓶頸以及過期和沒必要要的依賴包。

Webpack bundle analyzer 的示例
Webpack bundle analyzer 的示例

經過 VS CodeAtom 中的 Import Cost 擴展,咱們能夠明顯知曉導入包的大小。

VS Code 中的 Import Cost 拓展
VS Code 中的 Import Cost 拓展

實施代碼分割

只要有可能,咱們就應該只提供用戶體驗所必需的資源。向用戶發送一個完整的 bundle.js 文件,包括他們可能永遠看不到的交互效果的處理代碼,這不太理想(試想一下,在訪問着陸頁時,下載了處理整個應用程序的 JavaScript)。一樣,咱們不該處處提供針對特定瀏覽器或用戶代理的代碼。

Webpack 是最受歡迎的打包工具之一,默認支持代碼分割。最簡單的代碼分割能夠按頁面實施(例如着陸頁面的 home.js,聯繫頁面的 contact.js 等)。但 Webpack 提供了比較少的高級策略,例如動態導入或者懶加載,這可能值得研究。

考慮框架選擇

JavaScript 的前端框架突飛猛進。根據 2016 年的 JavaScript 現狀調查,React 是最受歡迎的。仔細評估架構選型可能會發現,你能夠採用更爲輕量級的替代方案,例如 Preact(須要注意的是,Preact 並非一個完整的 React 從新實現,它只是一個具備高性能,功能更輕的虛擬 DOM 庫)。一樣,咱們能夠將較大的庫替換爲更小的替代方案 —— moment.js 換成 date-fns(或者在特定狀況下,刪除 moment.js 中未使用的 locales)。

在開始一個新項目以前,有必要肯定什麼樣的功能是必需的,併爲你的需求和目標選擇性能最好的框架。有時這可能意味着選擇寫更多的原生 JavaScript。

📝 JavaScript 性能清單

  1. 監控 JavaScript 傳輸
  2. 移除沒必要要的依賴
  3. 實施代碼分割
  4. 考慮框架選擇

性能追蹤,前進之路

在大多數狀況下,咱們討論過的一些策略會對咱們正在打造的產品的用戶體驗產生積極的變化。性能多是一個棘手的問題,有必要長期跟蹤咱們調整的效果。

以用戶爲中心的性能指標

卓越的性能指標,旨在儘量接近描繪的用戶體驗。以往的 onLoadonContentLoaded 或者 SpeedIndex 對於用戶多久能與頁面進行交互給出的信息很是少。當僅關注資源傳輸時,咱們很難量化感知獲得的性能。幸運的是,有一些時間能夠很好地描述內容的可視性和互動性。

這些指標是白屏時間、首次有效渲染、視覺完整和可交互時間。

  • First Paint 白屏時間:瀏覽器從白屏到第一次視覺變化。
  • First Meaningful Paint 首次有效渲染:文字、圖像和主要內容都已可見。
  • Visually Complete 視覺完整:視口中的全部內容均可見。
  • Time to Interactive 可交互時間:視口中的全部內容均可見,而且能夠進行交互(JavaScript 主線程中止活動)。

這些時間和用戶體驗息息相關,所以能夠做爲重點進行追蹤。若是可能,將它們所有記錄,不然選擇一兩個來更好地監控性能。其餘指標也須要關注,特別是咱們發送的字節數(優化和解壓縮)。

設置性能預算

全部數據可能會很快變得使人困惑和難以理解。沒有可執行的目標,很容易迷失咱們最初的目的。幾年前,Tim Kadlec 寫過關於《性能預算》的概念。

遺憾的是,沒有什麼神奇的公式能夠設置它們。性能預算一般歸結爲競爭分析和產品目標,而這是每一個業務所獨有的。

設定預算時,重要的是要有明顯的差別,一般狀況下,至少要有 20% 的改善。實驗和迭代你的預算,能夠參考 Lara Hogan 的使用性能預算來接近新設計

使用性能預算計算器或者 Browser Calories Chrome 拓展程序來幫助你建立預算。

持續監控

性能監控應該是自動化的,市面上有不少提供全面報告的強大工具。

Google Lighthouse 是一個開源項目,它能夠審查性能、可訪問性、PWA 等。你能夠在命令行中或者直接在 Chrome 開發者工具中使用它。

Lighthouse 性能審查示例
Lighthouse 性能審查示例

對於持續的追蹤,能夠選擇 Calibre,它提供的性能預算、設備仿真、分佈式監控和許多其餘功能是咱們不在構建本身的性能套件上花費大量精力是完成不了的。

使用 Calibre 進行全面的性能追蹤
使用 Calibre 進行全面的性能追蹤

不管你在哪裏追蹤,請確保數據對於整個團隊或者小型組織裏的整個業務線都是透明和可訪問的。

性能是共同的責任,不只僅是開發團隊 —— 咱們都應對所建立的用戶體驗負責,無論是什麼角色或職級。

在產品決策或者設計階段,提倡速度和創建協做流程以發現可能的瓶頸是很是重要的。

創建性能意識和同理心

關心性能不只僅是一個業務目標(但若是你須要經過銷售統計數據來進行銷售,那可使用 PWA 統計)。這關乎於基本的同理心,並把用戶的最大利益放在第一位。

做爲技術人員,咱們的責任是,不要讓用戶的注意力和時間放在等待頁面上。咱們的目標是,創建有時間觀念和以人爲本的工具

提倡性能意識應該是每一個人的目標。讓咱們抱着性能和同理心,爲全部人創建一個更好、更有意義的將來吧。


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

相關文章
相關標籤/搜索