網際網路發展非常迅速,所以我們創造了Web平臺。通常我們會忽視連通性等問題,但使用者們卻不會視而不見。一瞥全球資訊網的現狀,可以發現我們並沒有用同情心、變通意識去構建它,更不要說效能了。
所以,今天的Web是什麼狀態呢?
在這個星球上的74億人中,只有46%可以上網。平均網路速度上限為7Mb/s。更重要的是,有93%的網際網路使用者正在通過移動裝置進行訪問——若不適配移動裝置將引起使用者反感。通常情況下,資料比我們假設的更昂貴——可能需要1到13小時才能購買500MB的資料包(德國 vs. 巴西;更有趣的統計資料參見 Ben Schwarz 的 Beyond the Bubble: The Real World Performance)。
我們的網站也不是完美的——平均網站是原始Doom遊戲的大小(約3 MB)(請注意,為了統計準確,應使用中位數,閱讀 Ilya Grigorik 的優秀“平均頁面”是一個神話,中檔網站大小目前為1.4MB)。影象可以輕鬆佔用1.7 MB的頻寬,而JavaScript平均值也有400KB的體積。這不僅是Web平臺的問題,原生應用程式可能更糟,還記得為了獲取錯誤修復版本,而下載200MB安裝包的情景嗎?
技術人員經常會發現自己處於特權狀態。隨著最新的高階膝上型電腦、手機和快速有線網際網路連線,很容易讓我們忘記,這些並不是每個人都有的條件(實際上,真的很少)。
如果我們從特權和缺乏同情的角度來構建網路平臺,那麼將導致排他性的糟糕體驗。
考慮到設計和開發的效能,我們怎樣才能做得更好?
優化所有資源
理解瀏覽器如何分析和處理資源,是顯著提高效能的最強大但未充分利用的方式之一。事實證明,瀏覽器在嗅探資源方面非常出色,同時解析並確定其優先順序。這裡是關鍵請求的來源。
如果請求中包含使用者視口中呈現內容所必需的資源,則該請求至關重要。
對於大多數網站,它將是HTML、必要的CSS、logo、網路字型,也可能是圖片。在許多情況下,幾十個其他不相關的資源(JavaScript、跟蹤程式碼、廣告等)影響了關鍵請求。幸運的是,我們能夠通過仔細挑選重要資源並調整優先順序來控制這種行為。
通過我們可以手動強制調高資源的優先順序,確保所需的內容按時呈現。這種技術可以顯著改善“互動時間”指標,從而使最佳的使用者體驗成為可能。
關鍵請求對許多人來說,似乎仍然是一個黑匣子,可共享資料的缺乏並不能改變現狀。幸運的是,Ben Schwarz
發表了關於這個問題的非常全面並平易近人的文章——關鍵請求。另外,請參閱Addy的文章,在Chrome中的預載入、預取和優先順序(Preload, Prefetch and Priorities in Chrome)。
[在Chrome開發人員工具中啟用優先順序]
要跟蹤在請求優先順序處理方面的情況,請使用Lighthouse效能工具和關鍵請求鏈稽核工具,或檢視Chrome開發人員工具中“網路”選項卡下的請求優先順序。
通用效能清單
- 積極地快取
- 啟用壓縮
- 優化關鍵資源的優先順序
- 使用CDN(Content Delivery Networks)
圖片優化
圖片通常佔網頁傳輸的大部分有效載荷,因此圖片優化可以帶來最大的效能提升。有許多現有的策略和工具可以幫助我們刪除額外的位元組,但是首先應考慮的問題是:“圖片對於我想傳達的資訊和效果至關重要嗎?”。如果可以消除它,不僅可以節省頻寬,而且還節省了請求。
在某些情況下,可以通過不同的技術實現類似的結果。比如CSS就具有藝術方向的一系列屬性,例如陰影、漸變、動畫及形狀,允許我們構造適當風格的DOM元素。
選擇正確的格式
如果不能捨棄圖片,確定哪種格式更合適就很重要了。首先要在向量和光柵圖形之間做出選擇:
- 向量圖形:解析度獨立,通常體積更小。非常適合logo、icon和簡單的圖形,包括基本形狀(線,多邊形,圓和點)。
- 光柵圖形:呈現更詳細的資訊,比較適合相片。
做出首個決定後,可以選擇以下幾種格式:JPEG、GIF、PNG–8、PNG–24,或最新的 WEBP 與 JPEG-XR 格式。有了這麼多的選項,如何確保我們做出正確的選擇?以下是找出最佳格式的基本方法:
- JPEG:顏色非常豐富的圖片(例如照片)
- PNG–8:色彩相對單一的圖片
- PNG–24:區域性透明的圖片
- GIF:動圖
Photoshop可以通過各種設定,例如降低質量、降低噪音或色彩數量來優化以上每一種格式。確保設計師瞭解上述效能實踐,並能夠使用正確的方式優化相應格式的圖片。如果您想了解更多如何處理圖片,請閱讀 Lara Hogan 的好文 Designing for Performance。
試用新格式
影象格式有幾個較新的玩家,即WebP、JPEG 2000 和 JPEG-XR。它們都是由瀏覽器廠商開發的:Google 的 WebP,Apple 的 JPEG 2000 和 Microsoft 的 JPEG-XR。
WebP 是最受歡迎的競爭者,支援無損和有失真壓縮,這使得它非常靈活。無損的 WebP 比 PNG 小26%,比 JPG 小25-34%。WebP 有著74%的瀏覽器支援,它可以安全地進行降級,最多可節省1/3的傳輸位元組。JPG 和 PNG 可以在 Photoshop 和其他影象處理應用程式以及命令列介面(brew install webp
)中轉換為WebP。
如果你想探索其他格式之間的視覺差異,推薦 Github 上這個很讚的 Demo。
用工具和演算法進行優化
即使使用了高效的影象格式,也不應跳過後處理優化。這一步很重要。
如果您選擇了尺寸相對較小的 SVG,它們也是可以再次壓縮的。SVGO 是一個命令列工具,可以通過剝離不必要的後設資料來快速優化 SVG。另外,如果您喜歡Web介面或受作業系統的限制,請使用 Jake Archibald 的 SVGOMG。因為 SVG 是基於 XML 的格式,它也可以在伺服器端進行 GZIP 壓縮。
ImageOptim 是大多其他影象型別的最好選擇。包括 pngcrush、pngquant、MozJPEG、Google Zopfli等,它在一個全面的開源包中捆綁了一大堆優秀的工具。ImageOptim 可以以 Mac OS 應用程式、命令列介面和 Sketch 外掛形式,輕鬆地實現到現有的工作流程中。對於那些在 Linux 或 Windows 上的場景,大多數 ImageOptim 的 CLI 都可以在您的平臺上使用。
如果您傾向於嘗試新興的編碼器,Google 今年早些時候釋出了 Guetzli——源自 WebP 和 Zopfli 的開源演算法。Guetzli 可以比任何其他可用的壓縮方法生成35%更小體積的 JPEG。唯一的缺點是:處理時間慢(CPU 每處理百萬畫素需要1分鐘)。
選擇工具時,請確保它們生成所需的結果並適應團隊的工作流程。理想情況是,將優化過程自動化,這樣就不會產生漏掉的情況。
響應式圖片
十年前,我們使用一種解析度,就可以為所有人服務,但時代變化太快,現今的響應式 Web 已非往日可比。這也是為什麼我們必須要特別留心,去精心優化視覺資源,確保它們適應各種視口裝置。幸運的是,感謝 Responsive Images 社群小組,我們可以完美使用 picture
元素和 srcset
屬性(二者都有85%+支援率)。
srcset 屬性
srcset
在解析度切換方案中效果最佳——即當我們需要根據使用者的螢幕密度和大小顯示影象時。基於srcset
和size
屬性中的一組預定義規則,瀏覽器將選擇最佳圖片,相應地提供給視口。這項技術可以帶來很大的頻寬和請求節省,特別是對於移動使用者。
[srcset 使用示例]
picture 元素
picture
元素和media
屬性旨在使藝術設計變得容易。通過為不同情形提供不同圖片(通過媒體查詢進行測試),無論什麼解析度,我們都能始終將影象中最重要的元素保持在焦點。
[picture 元素使用示例]
請務必閱讀 Jason Grigsby 的 Responsive Images 101指南,以便對這兩種方法進行徹底的闡述。
使用圖片 CDN 進行分發
視覺優化的最後一步是分發。所有資源都可以從使用 內容分發網路 中受益,但還有一些針對圖片優化的特定工具,例如 Cloudinary 和 imgx。使用這些服務的好處遠遠超過了減少伺服器上的流量,並顯著降低了響應延遲。
CDN可以很好的解決重圖片網站的複雜度,包括響應式服務與圖片優化。雖然產品不同(價格也是如此),但是大多數方案都是根據裝置和瀏覽器,調整大小、裁剪來確定哪種格式最適合使用者。甚至更多——它們可以壓縮、檢測畫素密度、水印、識別面部,並允許後置處理能力。藉助這些強大的功能,和將引數附加到URL的能力,以使用者為中心的圖片服務變得十分容易。
影象效能清單
- 選擇正確的圖片格式
- 儘可能使用向量圖形
- 如果變化不明顯,則降低圖片質量
- 使用新格式圖片
- 使用工具與演算法優化
- 學習
srcset
和picture
- 使用圖片 CDN
Web 字型優化
自定義字型是一項非常強大的設計工具。但是能力伴隨著很多責任。現有68%的網站在使用 Web字型,這種型別的資源是效能殺手之一(平均輕鬆可達100KB,取決於變體和字型的數量)。
即使體積不是最大的問題,不可見文字閃動(FOIT)也算是。當Web字型載入中或載入失敗時,會發生FOIT,這會讓空白頁面,從而導致內容無法訪問。首先仔細檢查我們是否需要Web字型可能是值得的。如果真是這樣,有一些策略可以幫助我們減輕對業務的負面影響。
選擇正確的格式
有4種網路字型格式:EOT、TTF、WOFF 和最近的 WOFF2。TTF 和 WOFF 被廣泛使用,擁有超過90%的瀏覽器支援率。根據支援情況,最有可能安全地使用WOFF2,並在舊版瀏覽器降級使用 WOFF。使用WOFF2的優點是,一套定製的預處理和壓縮演算法(如Brotli),並有大約30%的檔案大小減少和改進的解析能力。
在@font-face
中定義網頁字型的來源時,請使用format()
提示來指定應使用哪種格式。
如果您使用 Google Fonts 或 Typekit 來提供字型,這兩種工具都實施了一些策略來優化其效能。Typekit 現在可以非同步地為所有套件提供服務,防止 FOIT 以及允許其JavaScript套件程式碼的10天延長快取期限(而不是預設10分鐘)。Google Fonts 可以根據使用者裝置自動提供最小的檔案。
稽核字型範圍
無論是否自主託管,字型數量、字型體積和樣式,都將顯著影響您的效能預算。
理想情況下,我們只需要一種包括常規和粗體的字型。如果您不確定如何選擇字型範圍,請參考 Lara Hogan 的 Weighing Aesthetics and Performance。
使用Unicode範圍子集
Unicode範圍子集允許將大字型分割成較小的集合。這是一個相對先進的策略,特別是在處理亞洲語言的時候,可能會帶來顯著的節省(你知道中文字型有平均數為 20,000 個字形嗎?)。第一步是將字型限制為必要的語言集,例如拉丁語,希臘語或西里爾語。如果僅使用Web字型做Logo類使用,則應使用Unicode範圍描述符,來選擇特定字元。
Filament Group 釋出了一個開源命令列工具,可以根據檔案或URL生成必要字形列表的 glyph hanger。或者,基於 Web 的 Font Squirrel Web Font Generator 提供高階子集和優化選項。如果在字型選擇器介面中內建了使用Google Fonts 或 Typekit 選擇語言子集,則使基本子集更容易。
建立字型載入策略
字型是阻塞渲染的——因為瀏覽器必須首先構建 DOM 和 CSSOM;在使用與現有節點相匹配的CSS選擇器之前,瀏覽器並不會下載Web字型。這種行為會明顯延遲文字呈現,通常會導致前面提到的不可見文字閃動(FOIT)。在較慢的網路和移動裝置上,FOIT會更加顯著。
實施字型載入策略,可防止使用者無法訪問您的內容。通常,選擇無樣式文字閃動(FOUT)是最簡單和最有效的解決方案。
font-display
是提供非 JavaScript 依賴解決方案的新 CSS 屬性。不幸的是,它僅有部分支援(Chrome 和 Opera),目前正在 Firefox 和 WebKit 中開發。儘管如此,它可以並且應該與其他字型載入機制結合使用。
[font-display 屬性實踐]
幸運的是,Typekit 的 Web Font Loader 和 Bram Stein 的 Font Face Observer 可以幫助管理字型載入行為。此外,網頁字型效能專家 Zach Leatherman 釋出了字型載入策略綜合指南,這將有助於為您的專案選擇正確的方法。
字型效能清單
- 選擇正確的格式
- 稽核字型範圍
- 使用Unicode範圍子集
- 建立字型載入策略
JavaScript 優化
目前,JavaScript 的平均大小為446 KB,已經使其成為第二大的資源型別(第一為圖片)。
我們可能沒有意識到,我們所愛的JavaScript隱藏著更加嚴峻的效能瓶頸。
監控JavaScript的流量
優化交付只是解決網頁膨脹的第一步。JavaScript 下載後,必須由瀏覽器進行解析、編譯和執行。快速瀏覽一些流行的網站,顯而易見的是,gzip 壓縮的 JS 在解壓之後至少變大三倍。事實上,我們正在傳送一大堆程式碼。
1MB JavaScript 在不同裝置上的解析時間。圖片由 Addy Osmani 和他的 JavaScript Start-up Performance 文章提供。
分析解析和編譯時間,對於理解應用程式是否準備好進行互動至關重要。這些耗時根據使用者裝置的硬體能力而異。解析和編譯會很容易在低端手機上高出2-5倍。Addy的研究證實,在常規手機上,一個應用程式將需要16秒才能達到互動式狀態,而在桌面電腦上為8秒。分析這些指標至關重要,幸運的是,我們可以通過 Chrome DevTools 來完成。
[在 Chrome 開發工具中檢視解析和編譯過程]
請務必閱讀 Addy Osmani 對 JavaScript 啟動效能的詳細說明。
擺脫不必要的依賴
現代軟體包管理器的工作方式,可以輕而易舉地掩蓋依賴關係的數量和大小。webpack-bundle-analyzer 和 Bundle Buddy 是很好的視覺化工具,幫助識別出程式碼重複、最大效能問題和過時的、不必要的依賴。
圖 webpack bundle analyzer 實踐(譯者注:原gif太大,只能用外鏈了)
通過 VS Code 和 Atom 中的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 效能清單
- 監控 JavaScript 流量
- 擺脫不必要的依賴
- 實現程式碼分割
- 考慮框架選擇
效能追蹤,前進之路
我們已經討論了一些策略,在大多數情況下會對我們正在建立的產品使用者體驗產生積極的變化。效能可能是一個棘手的問題,有必要長期地跟蹤我們調整的結果。
以使用者為中心的效能指標
卓越的效能指標,旨在儘可能接近描繪使用者體驗。以往的onLoad
,onContentLoaded
或SpeedIndex
對「使用者多快能與頁面互動」給出的資訊非常少。當聚焦到傳輸資源時,量化地感知效能十分困難。好在,有一些時間可以全面地描述內容的可視性和互動性。
這些指標是首次渲染(First Paint),首次有意義渲染(First Meaningful Paint),視覺完整(Visually Complete)和可互動時間(Time to Interactive)。
- 首次渲染:瀏覽器從白色螢幕到第一次視覺呈現的變化。
- 首次有意義渲染:文字,影象和主要內容都已可見。
- 視覺完整:視口中的所有內容都可見。
- 可互動時間:視口中的所有內容都是可見的,可以與之進行互動(JavaScript 主執行緒停止活動)。
這些時間直接對應於使用者的實際體驗,因此可以作為重點進行追蹤。如果可能,將它們記錄全部,否則選擇一兩個來更好地監控效能。其他指標也需要留意,特別是我們傳送的位元組數(優化和解壓縮)。
設定效能預算
所有這些上報數字可能會很快變得混亂和不易理解。沒有可操作的目標和物件,很容易迷失我們最初的目的。幾年前,Tim Kadlec 寫過關於效能預算的概念。
遺憾的是,並沒有一個萬能的神奇公式。效能預算通常歸結為競爭分析和產品目標,而這是每個業務所各異的。
設定預算時,重要的是要達到明顯的差異,通常是至少改善20%。實踐和迭代您的預算,利用 Lara Hogan 的方法新設計與效能預算作為參考。
試用效能預算計算器或Chrome擴充套件瀏覽器卡路里,以幫助建立預算。
持續監控
監控效能不應該是手動的。市面上有很多強大的工具,還可以提供全面的報告。
Google Lighthouse 是一個可以稽核效能、可訪問性、漸進式網路應用程式等的開源專案。您可以在命令列中或直接在 Chrome Developer Tools 中使用Lighthouse。
[Lighthouse 執行一次效能審查]
對於持續的追蹤,選擇選擇 Calibre,它可以提供效能預算、裝置模擬、分散式監控和許多其他功能,無需我們仔細構建自己的效能套件即可獲得。
[Calibre 報表]
無論您在追蹤什麼,請確保使整個團隊或組織能夠透明地訪問資料。
效能是一項分擔責任,遠遠超過開發人員團隊——我們都應對所建立的使用者體驗負責,不管是什麼角色或職級。
倡導速度和建立協作流程,以便在產品決策或設計早期階段,儘早暴露可能遇到的瓶頸,是非常重要的。
建立效能意識和同情心
關心效能不僅僅是一個業務目標(但是如果您需要通過銷售統計資料來進行銷售,那麼可以通過PWA統計)。這是關於基本的同情和使用者體驗放在第一位。
作為技術專家,我們的責任是,不要讓使用者的注意力和時間放在等待頁面上,而已可以更開心地花費在其他地方。我們的目標是建立意識到時間和人們關注的工具。
提倡效能意識應該是每個人的目標。讓我們抱著效能和同情心,為大家建立一個更好、更有意義的未來吧。