原文地址:http://www.smashed.by/perf-checklist 做者 | Vitaly Friedman 譯者 | OpenWeb開發者 三三前端
衆所周知,性能十分重要。然而,咱們真的知道性能瓶頸具體在哪兒嗎?是執行復雜的 JavaScript,下載緩慢的 Web 字體,巨大的圖片,仍是卡頓的渲染?研究搖樹(Tree Shaking),做用域提高(Scope Hoisting),或是各類各樣的與 IntersectionObserver、Clients Hints、CSS containment、HTTP/2 和 Service Worker 一同工做的華麗的加載模式真的有價值嗎?最重要的是,咱們從哪裏開始優化性能,以及咱們如何創建長期的性能文化呢?git
之前,性能每每只是過後的想法。一般直到項目最後的時候纔會被考慮,而後被歸結爲壓縮、合併、靜態資源優化或者對服務器配置文件的一些細微調整。如今回想起來,事情彷佛已經發生了很大的變化。github
性能不只僅是一個技術問題:它很重要,並且當把它引入到工做流時,設計決策必須根據其性能影響來決定。咱們必須不斷的測量、監視和改進性能,並且 Web 日益複雜的狀況帶來了新的挑戰,使得性能指標難以被跟蹤,由於性能指標將因設備、瀏覽器、協議、網絡類型和延遲(CDN、運營商、緩存、代理、防火牆、負載平衡器和服務器都在其中發揮做用)而有很大差別。數據庫
所以,若是咱們創做一個在提升性能時必須牢記的全部事項的概述——從流程的一開始到網站的最終發佈——這樣的列表將是什麼樣子?下面就是 2018 前端性能檢查表(希望不偏不倚和足夠客觀)——說明您可能須要考慮的問題,以確保您的站點響應時間快、用戶交互流暢,而且不會用盡用戶的帶寬。瀏覽器
下面是您可能須要考慮的前端性能問題的概述,以確保您的響應時間快速而流暢。緩存
(譯註:原文詳細地闡述了文中所涉及的全部優化策略的原理和前因後果。此處僅翻譯了原文中附帶的 PDF 檢查表文件,意在提供一個快速、簡潔的性能優化清單。)安全
只要團隊之間沒有協做,高性能就沒法長期維持。研究用戶反饋中常見的抱怨,看看提升性能是否能夠幫助緩解其中一些問題。用真實數據來創建適合本身的案例和模型。在設計過程當中就開始規劃加載順序和權衡。性能優化
並不是每一個指標都同等重要。研究最重要的度量標準:通常而言,它與您開始渲染最重要像素的速度以及提供輸入響應的速度有關。根據客戶的感覺肯定頁面加載的優先級。可交互時間、頁面大標題元素的渲染時間、首次有效繪製時間(FMP)、速度指數(Speed Index)通常都很重要。服務器
收集表明您受衆的設備上的數據。在數據來源上,真實設備比模擬數據更好。選擇一臺 Moto G四、中端三星設備或者 Nexus 5X 等性能良好的中端設備。或者,也能夠經過在電腦上,經過設置網絡限速(例如:150ms RTT,1.5Mbps 下載,0.7Mbps 上傳)和 CPU 限速(5 倍慢速)以模擬移動體驗。最後在常規 3G、4G 和 Wi-Fi 之間切換。收集數據、設置電子表格、將指標提升 20% 並設置目標(即,「性能預算」)。babel
確保團隊中的每一個成員都熟悉該清單。每個決策都涉及性能問題,前端開發人員的積極參與將使您的項目受益不淺。將你的性能預算映射到設計決策上。
每幀動畫應在少於 16 毫秒(理想狀況下爲 10 毫秒)內完成,從而達到每秒 60 幀(1 秒 ÷ 60 = 16.6毫秒)。保持樂觀,明智地利用空閒時間。對於像動畫這樣的高壓點,只要能,就不要作任何其它事情。預計輸入延遲時間(Estimated Input Latency)應低於 50 毫秒。
目標是在 1 秒內(在高速網絡下)完成首次繪製(FMP),速度指數(SpeedIndex)低於 1250 毫秒。考慮速度基線是一臺有着 3G 網絡的,價格爲 200 美圓左右的 Android 手機(譯註:國產千元機水平),那麼能夠以 400 毫秒 RTT 和 400kb/s 的傳輸速度進行網絡模擬,以達成可交互時間(Time-To-Interactive)小於 5 秒,第二次打開的速度低於 2 秒。盡你所能地下降這些指標。
HTML 的前 14~15kb 是最關鍵的核心塊(chunk),也是整個文件中惟一能夠在第一個 RTT 內被下載的部分。要實現上述目標,請設定關鍵文件的最大尺寸「預算」。170kb gzip 後的文件(原始文件尺寸 0.8~1mb),在普通手機上可能須要 1 秒才能解析和編譯完成。
不要太注意所謂的「酷」。只要您可以快速得到結果,並且在維護構建過程上沒有問題就很好了。
首先設計和構建核心功能,而後再在此基礎上爲功能強大的瀏覽器的高級功能加強效果,從而建立彈性的體驗。若是您的網站在性能差、網絡差的機器上還能運行得比較快,那在性能好、網絡棒的機器上只會運行得更快。
用 JavaScript 實現交互效果的成本至關高昂。170kb 的尺寸預算已經包含了核心的 HTML / CSS / JavaScript、路由、狀態管理、工具函數、框架還有產品邏輯,所以,請完全檢查咱們選擇的框架的網絡傳輸成本、解析 / 編譯時間和其運行時的時間成本。
並非每一個項目都須要框架。可是若是你的項目須要框架,那麼最好選擇使用一個支持服務器端渲染(SSR)的框架。在使用框架以前,請確保在移動設備上以服務器端渲染和客戶端渲染兩種模式來評估框架的啓動時間。瞭解您將依賴的框架的具體細節。瞭解 PRPL 模式和 App Shell 模型。
(譯註:AMP 爲 Google 的開源項目,意在以組件化的形式以提高移動設備對網站的訪問速度;Instant Articles 是 Facebook 的協議,意在經過渲染頁面的精簡版本以提高頁面在 Facebook App 內的打開速度。在國內,MIP 是和 AMP 相似的解決方案。)
沒有它們,你也能夠得到良好的性能。可是 AMP 提供了一個可靠的性能框架,有免費的 CDN ,而 Instant Articles 將提升你在 Facebook 上的知名度和性能。你也能夠構建一個漸進式 AMP(譯註:Progressive Web AMP,PWA 和 AMP 的結合體)。
您能夠將部份內容「外包」給靜態站點生成器,而後將其推送到 CDN,並從CDN 提供靜態版本,從而避免數據庫請求(即 JAMStack)。固然,這取決於您擁有的動態數據量。仔細檢查 CDN 是否爲您執行了內容壓縮和轉換、智能 HTTP/2 和邊緣端包含(ESI, edge-side includes)。
把你全部的靜態資源(JavaScript,圖片,字體,第三方腳本,尺寸大的模塊)列成一個表,而後把它們按優先級分紅三組:基本核心功能(老瀏覽器也能瀏覽的核心內容)、加強體驗效果(爲現代瀏覽器設計的強大功能和豐富體驗)、附加功能(不必定須要而且能夠惰性加載的資源,好比字體、輪播腳本、視頻播放器、分享按鈕等)。
(譯註:「符合標準」技術(cutting-the-mustard technique)是 BBC News 開發者博客提出的,一種基於瀏覽器特性來檢測其支持程度,並以此選擇要加載哪些功能的技術。)
對老舊的瀏覽器,僅輸出核心功能代碼;對現代瀏覽器輸出加強的功能代碼。嚴格按標準加載靜態資源:直接加載核心代碼,在 DOMContentLoaded 事件中加載加強代碼,並在 load 事件中加載剩下的代碼。注意:廉價的 Android 手機雖然很符合標準,但這些手機的內存和 CPU 性能有限。所以,您可能須要使用讀取設備內存大小的 JavaScript API 來檢測設備性能,只有不支持的時候才按「符合標準」技術來。
因爲解析 JavaScript 很耗時,因此請儘量的減小 JavaScript 的體積。在構建 SPA 時,您可能須要用必定時間初始化應用程序以後,才能開始渲染頁面。尋找能夠加快初始渲染事件的模塊和技術(在低端移動設備上,這能夠輕鬆將速度提升 2-5 倍)。完全檢查每個 JavaScript 依賴,以找出誰在消耗初始化的寶貴時間。
使用服務器端渲染來得到快速的首次有效繪製時間(FMP),但也在頁面裏輸出一些最小功能的 JavaScript 來保持交互時間(TTI)接近首次有效繪製時間(FMP)。而後,若是有須要或者有多餘的時間,纔開始啓動應用程序的非必要部分。在加載時顯示一個骨架屏幕,而不是「加載中」動畫。
使用搖樹(Tree Shaking)技術和代碼分割(Code Splitting)技術以減小代碼體積。
搖樹(Tree Shaking)技術是一種經過丟棄未使用的代碼以在構建過程清理代碼的方法。代碼分割(Code Splitting)技術將您的代碼拆分爲按需加載的「chunks(塊)」。做用域提高(Scope Hoisting)技術使得鏈式的依賴能被無縫地轉換成行內函數。經過 WebPack 將上述技術用於您的代碼。使用 AOT 編譯器(譯註:例如 Closure Compiler)將一些客戶端計算移到服務端。
做爲開發者,咱們必須顯式地使用 defer
和 async
屬性來告訴瀏覽器不要等待腳本下載、開始渲染頁面。若是你不須要關注 IE 9 及如下版本的瀏覽器,那麼使用 defer
更好;不然,使用 async
更好。使用靜態的分享按鈕、靜態連接交互式地圖而不是使用第三方庫。
從新檢查你是否正確的設置了 Expires, Cache-Control, Max-Age 等 HTTP 緩存控制響應頭。一般而言,一個資源要麼只被緩存很短的時間(好比常常修改的資源),要麼永久緩存(好比不會被更改的那種資源)。使用專爲帶哈希指紋的靜態文件設計的響應頭 Cache-Control: imuutable
以免瀏覽器從新請求文件。
Brotli 是一種新的無損壓縮格式。如今,全部的現代瀏覽器都支持它。它比 Gzip 和 Deflate 壓縮率更高,壓縮很是慢,可是解壓速度很快。使用最高壓縮比的 Brotli+Gzip 預壓縮靜態文件,並使用 1~4 級的 Brotli 實時壓縮動態內容。也順便檢查一下 CDN 是否支持 Brotli。或者,你也能夠試試在不常變化的資源上使用 Zopfli —— 它將數據用 Deflate、Gzip 和 Zlib 格式壓縮,而且被設計爲一次壓縮、屢次下載。
儘量使用經過 srcset
、sizes
和 <picture>
元素實現的響應式圖片。使用 WebP 格式的圖片;這可經過 <picutre>
標籤配合 JPEG fallback,或者經過 Accept
請求頭來實現。對於核心圖片,使用漸進式的 JPEG 並用高斯濾鏡模糊掉不重要的部分。
您使用的 Web Font 極可能包含未真正被使用的執行和額外的特性。製做字體的子集(譯註:僅包含部分文字的字體,如 fontmin 等方案)。優先使用 WOFF2 並使用 WOFF 做爲後備。當即使用後備字體顯示文字、異步加載字體(例如,使用 loadCSS),而後再切換字體。同時也考慮本地操做系統中已經安裝了的字體。不要忘記在 CSS 中寫 font-display: optional
;若是你沒法從您的服務器加載字體,請記得使用 Font Load Events。
將全部首屏渲染所須要的 CSS 放在一塊兒,而後方法在 <head>
標籤中。考慮有選擇的內聯的方法。或者,使用 HTTP/2 服務端推送;但這樣你可能須要構建一個可感知緩存的 HTTP/2 服務端推送機制。
因爲 ES2015 已被普遍支持了,您能夠考慮使用 babel-preset-env
以僅轉譯現代瀏覽器不支持的 ES2015+ 特性。而後你能夠編譯兩份,一份是 ES6 ,另外一份是 ES5。使用 <script type="module">
使得有 ESM 支持的瀏覽器加載新文件,剩下的老的瀏覽器可使用 <script nomodule>
來加載老的文件。
使用 CSS 包含(CSS Containment)隔離渲染十分耗時的組件。請保證在滑動頁面或者元素動畫的時候,頁面不會卡頓,並且你的頁面能持續以 60fps 的速度渲染。若是那不可能,那麼至少也要把 fps 控制在 15~60 之間。使用 CSS 的 will-change
屬性通知瀏覽器哪一個元素將會變化。
Intersection Observer API 提供了異步監聽目標元素與祖先元素或頂層文檔視口交點中的更改的能力。瀏覽器支持?Chrome, Firefox, Edge 和三星瀏覽器都支持了。WebKit 還在開發。瀏覽器不支持?懶加載一個 polyfill。
不要低估感知性能的做用。在加載靜態文件時,儘可能始終領先用戶一步,這樣在後臺發生不少事情時,會感受體驗上很快。例如,要讓用戶持續關注你的頁面,請使用骨架屏幕而不是一些加載中的動畫。
使用骨架屏幕,而後懶加載全部的大型組件,好比字體、JavaScript、輪播圖、視頻和 iframe 等。使用資源提示(Resource Hints),如 dns-prefetch
、preconnect
、prefetch
和 preload
來節省時間。
HTTP/2 支持很好,並且提供了不小的性能提高。缺點是,您必須遷移到 HTTPS;根據您不支持 HTTP/2 的用戶羣大小,你可能須要爲 HTTP/1.1 和 HTTP/2 的用戶返回不一樣版本的代碼,這就要求您調整您的編譯工具。
您須要在打包模塊和並行加載許多小模塊之間找到一個良好的平衡。將整個界面分解爲許多小模塊;而後分組、壓縮和打包。整個網站分爲大約 6 到 10 個包應該是一個不錯的折衷方案(對於傳統瀏覽器來講也不錯)。經過實驗和數據監測來爲您的網站找到正確的平衡。
Save-Data 請求提示頭可讓咱們爲關心流量費用和性能的用戶提供個性化的響應。例如,你能夠把全部高清的圖片都改爲低清的,不用 Web Font 和華麗的動效,關掉視頻自動播放和服務器推送,甚至修改你的應用界面。
再次檢查安全標頭是否設置正確,消除已知漏洞,並檢查 SSL 證書。確保全部外部插件和跟蹤腳本都是經過 HTTPS 加載的、沒有 XSS,而且 HSTS 響應頭和內容安全策略(CSP)響應頭都已正確設置。
不一樣的服務器和 CDN 可能對 HTTP/2 有不一樣的支持。使用 Is TLS Fast Yet? 來檢查你的設置,或者直接看看你的服務器性能如何,支持的特性狀況怎麼樣。
在服務器上啓用 OCSP Stapling 有助於提高 TLS 握手速度。OCSP 協議可讓瀏覽器無需下載並檢索證書信息,從而減小握手時間。
研究標明,IPv6 的鄰居發現(NDP)和路由優化可使網站快 10% ~ 15%。升級到支持 IPv6 的 DNS 覺得將來作好準備。只需確保雙棧網絡能正常工做——這使得 IPv6 和 IPv4 能同時運行。畢竟,IPv6 不是向後兼容的。
若是你使用了 HTTP/2,再次檢查你的服務器是否實現了 HPACK 壓縮。HPACK 壓縮能夠壓縮 HTTP 響應頭,以減小沒必要要的開支。因爲 HTTP/2 服務器如今都很新,他們可能不能徹底支持包括 HPACK 壓縮在內的全部標準。H2spec 是一個很是好的用於檢測標準支持程度的工具。
網絡再怎麼優化,也不會比本地緩存更快。若是你的網站使用了 HTTPS,那麼你能夠把靜態資源放在 Service Worker 的緩存中,而不用請求網絡。
若是您最近從 HTTP 遷移到了 HTTPS,請確保使用相似 Report-URI.io 之類的服務監控了嚴格的或被動的混合內容報警。你也能夠用 Mixed Content Scan 來掃描你的 HTTPS 站點上是否有非 HTTPS 的混合內容。
選擇一個調試工具,並試着點擊每個按鈕。請確保您理解如何分析渲染性能、控制檯輸出、調試 JavaScript 和編輯 CSS 樣式。
在 Chrome 和 Firefox 上測試是不夠的。請看看你的網站在代理瀏覽器和老式瀏覽器(包括 UC 瀏覽器和 Opera Mini 等。譯者注:此處的代理瀏覽器即指國內瀏覽器中常見的雲加速功能)上是什麼樣子。統計你受衆國家的網絡平均速度,避免出現重大意外。使用網絡節流並模擬高 DPI 設備。雖然 BrowserStack 很好,但也得在真機上測試。
良好的性能指標是被動和主動監控工具的組合。擁有 WebPagetest 的私有實例和使用 Lighthouse 確實有利於快速測試,但也須要使用諸如 Calibre、speedscurve 等 RUM 工具創建持續的監控體系。設置您本身的用戶計時打點以監控特定的業務速度指標。
此列表至關全面,完成全部優化可能須要至關長的時間。若是你只有一個小時的時間,但又想得到顯著的提高,你應該怎麼作?咱們挑出了 10 個最容易實現的方法。顯然,在開始以前和完成以後,請統計結果,包括 3G 和有線鏈接上的開始渲染時間和速度指數(SpeedIndex)。
<head>
標籤裏(你的預算是 14KB)。對於 CSS/JS,請保證核心文件尺寸最大爲 170kb (gzip 後的尺寸;壓縮前 0.8~1Mb)dns-lookup
, preconnect
, prefetch
和 preload
。Huge thanks to Yoav Weiss, Addy Osmani, Artem Denysov, Denys Mishunov, Ilya Pukhalski, Jeremy Wagner, Colin Bendell, Mark Zeman, Patrick Meenan, Leonardo Losoviz, Guy Podjarny, Andy Davies, Rachel Andrew, Anselm Hannemann, Patrick Hamann, Andy Davies, Tim Kadlec, Rey Bango, Matthias Ott, Mariana Peralta, Philipp Tellis, Ryan Townsend, Mohamed Hussain S H, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson and Rodney Rehm for reviewing this article, as well as our fantastic community, which has shared techniques and lessons learned from its work in performance optimization for everybody to use. You are truly smashing!
BOW(Brilliant Open Web)團隊,是一個專門的Web技術建設小組,致力於推進 Open Web 技術的發展,讓Web從新成爲開發者的首選。BOW 關注前端,關注Web;剖析技術、分享實踐;談談學習,也聊聊管理。關注 OpenWeb開發者(ID:BrilliantOpenWeb)公衆號,回覆「加羣」,讓咱們一塊兒推進 OpenWeb技術的發展!