[譯]網路效能入門:2019年初學者指南

smallbone發表於2018-12-29

原文地址:Getting started with web performance: 2019 beginner’s guide
原文作者:Jakub Gieryluk
譯文出自:FE-star/speed
譯者:smallbonelu
校對者:[]
本文連結:[]

有很多非常好的文章介紹了關於如何使用新功能X或技術Y亦或工具Z來提高網站效能。如果你對該主題不熟悉,那麼瀏覽現代網路效能的迷宮可能會很困難。在本文中,我將嘗試提供一個指南,以開始你的效能之旅。

瞭解你的使用者

在開始之前,最好知道你的使用者是誰以及他們如何使用你的網站,以便以後做出明智的決定。從效能方面來看,重要的事情是:

  • 移動與桌面瀏覽器的使用者的比例,
  • 通過瀏覽器引擎來劃分使用者:類似Chrome,Safari,Firefox,Edge,IE,
  • 按國家劃分使用者。

你很可能已經使用了可以回答這些問題的分析工具。花一些時間來分析這些資料並將其寫下來,包括分析日期,以便在需要時輕鬆訪問,並在幾個月內進行重新評估和比較。

請注意,全域性統計資訊通常與本地統計資訊不同:特別是在資料成本較高的國家/地區,UC瀏覽器,Opera Mini等瀏覽器非常受歡迎,而其他地方几乎未使用過。

要了解使用者的真實瀏覽體驗,以及你的網站與競爭對手的比較情況,你可能需要檢視Chrome UX報告

確定測試URL

提出一些URL,這些URL將成為效能分析和優化的候選者代表。你可能希望某些URL's能夠獲得大量流量,隨著時間的推移擁有相對穩定的內容,並且可以很好地覆蓋你的網站的各種功能

你的首頁是自然的第一候選者。對於部落格或新聞網站,過去流行的文章將是另一個候選者。

例如,Wikimedia的效能團隊使用英語維基百科的“Barack Obama”和“Sweden”文章進行基準測試和效能監控。

瞭解這些工具

在幾個效能工具中執行你的頁面,以熟悉它們並確定一些“速效方案”。不同的工具可能提供其他工具缺失的見解,或者可能比其他工具解釋得更好 - 所以值得試一試所有的這些工具,看看哪些對你的特定用例最有用。

  • Lighthouse可能是最容易上手的工具,它提供了大量有關重度依賴JS的現代Web應用程式的詳細資訊:可以通過在Chrome瀏覽器開發工具的“Audit"選項卡中來執行,或者從任何瀏覽器本地執行web應用程式WPT
  • WebPageTest 是網路效能的“瑞士軍刀”,非常強大,併為高階使用者提供了許多“隱藏功能”。你進入webperf的次數越多,你使用它的次數也就會越多。電影膠片和視訊比較檢視是它的一些殺手級功能。Using WebPageTest一書是一個很好的參考。
  • Yellow Lab Tools 還可以提供各種效能指標的有用細分。
  • 雖然不是嚴格關注效能,但是也可以通過WebHintRedBot檢視一下,它們可以發現你網站的互操作性和正確性問題,提出改進建議,並幫助你擺脫無用的HTTP頭。
  • 另請參閱SiteSpeed.io以獲取大量開源webperf工具。
  • 除此之外,還有許多商業效能監控服務,其中一些還提供有限的免費工具。

在這一點上,你已經知道一些相對容易修復的問題(至少在理論上),但影響很大:比如未壓縮資源,未優化圖片等。

瞭解你網站的HTML

獲取你網站的HTML輸出(也就是頁面原始碼)(例如在Firefox和Chrome中使用快捷鍵Ctrl-U),重新格式化並進行分析。建立一個關於哪些標籤組成了你的HTML的高階文件,為什麼會使用這些標籤(如果你不知道,請詢問你的同事),以及佔用了多少位元組。

在長期維護的專案中,多年來積累的一些標籤可能已經不再需要,那麼就可以安全地移除它們。(如果它是第三方JavaScript庫,那就附加獎勵了!)

瞭解你網站的子資源

接下來的事情是明白你的網站,瞭解一個頁面的載入觸發了哪些HTTP請求,何時觸發以及為什麼會觸發。執行WebPageTest測試,將所有請求的列表(在底部)複製到電子表格,並分析每個請求的角色(特別是列表中的前10-20個),以及它們的重要程度可能會有所幫助。使用圖表軟體建立流程圖可能對更好地理解它們之間的依賴關係關係也很有用。

如果你不確定給定請求的作用,你也許可以嘗試阻止請求或人為的引入較大的延遲並檢視網站的行為(這對於發現意外的單點故障依賴關係也很有用)。這有無數種方法可以做到:Chrome開發工具的*“Request blocking”功能,Fiddler 的“AutoResponder”(具有延遲)功能,以及WebPageTest的“Block”“SPOF”*功能; 即使是任意瀏覽器中的廣告攔截器都可以實現。

通過了解哪些請求對使用者體驗至關重要,哪些請求是次要的,你可以更好地確定優化工作的優先順序。如果可能,請非同步載入你的指令碼使用defer

RequestMap是一個可用於 稽核來自你的webapp的第三方請求的工具,並可幫助你發現通常不利於網站效能的長鏈請求。

隔離功能的方法

複雜的Web應用程式通常必須實現許多功能並觸發許多請求; 同時分析所有這些並不總是那麼容易。通過能夠輕易禁用的某些功能(例如通過查詢字串),你可以讓你的生活更美好。

小範圍地測試

面向效能的瀏覽器功能通常是非常新的,因此尚未經過實戰測試,這些功能可能在不同的瀏覽器中存在一些難以察覺的錯誤或實現的行為略有不同。 當你將新瀏覽器功能直接應用於現實中的大型專案時,瞭解新瀏覽器功能的確切工作原理也可能會非常棘手。

一個好主意可能是回到基礎部分,建立小的隔離HTML頁面進行測試,將它們部署到公共伺服器(我使用GitHub Pages),並在所有主流瀏覽器中執行WebPageTest測試。

由於統一的WebPageTest UI,所以可以輕鬆地比較瀏覽器引擎的行為 - 比檢視不同的開發工具介面要容易得多。如果你發現了一些意外行為,那麼你已經有一個簡化版的測試用例可以用來向瀏覽器廠商提交錯誤報告。

想一想要測量什麼

大多數早期優化(如刪除/壓縮assets)都可以安全地執行,並且會立即帶來明顯的改進,通常不會導致回退。但是為了更進一步和基於長期發展的考慮,你需要確切地知道你的KPI是什麼以及如何衡量它們

這可能非常難以定義,它在很大程度上取決於你擁有的網站/網路應用程式型別。瀏覽器觸發loadDOMContentLoaded事件的時間等“傳統”指標並不適合現代網站,更不用說重度依賴JS的SPA了(單頁面應用程式)。在任何情況下,請忘掉“one number to rule them all”。你很可能需要多個指標來了解全貌。

瞭解現有的效能指標

除了難以定義之外,某些事情仍難以準確測量,特別是視覺事件(“我的圖片和文字何時變得可見?”)。這很難回答,因為文字呈現可能取決於外部CSS和webfonts的可用性(如果它們正在等待下載,這可能導致所謂的不可見文字閃爍),而圖片的load事件的觸發也不能精準的知曉了(與在螢幕上實際渲染畫素的時間相比)。

直到最近,瀏覽器根本沒有提供足夠的細節來衡量渲染效能,而WebPageTest的Speed IndexVisually Complete也就成為了金律。這些是非常複雜的指標,是通過獲取一系列螢幕截圖並分析渲染內容隨時間變化的方式建立的,但你應該花一些時間來理解它們 ; 它們比簡單的指標更好地傳達使用者體驗。

話雖如此,瀏覽器(特別是Chrome)在2018年在這個領域取得了一些進展,它釋出了像PerformanceObserver這樣的瀏覽器內建APIs,這個APIs提供了諸如First Contentful PaintFirst Meaningful Paint等事件。如果你對細節感興趣,請檢視Paul Irish的演講

建立自定義指標

除了現成的指標外,你可能還需要一些於你網站的特定的自定義指標; 也許是將你的JavaScript程式碼中自定義事件的時間戳與資源的獲取時間和大小相結合,這些資訊可以從Resource Timing API來獲取。

在建立自定義指標時,你可能需要混合使用定義明確,細粒度,可操作的指標(例如,“JavaScript method1()和method2()呼叫之間的時間”以及可以傳達真實使用者體驗的更高階別指標(例如“從HTML的responseStart到一個myImportantAppLifecycleEvent“的時間)。前者是明確致力於改進給定指標(以及捕捉意外回退)的良好基準。後者不太容易隨著大型重構和程式碼更改而變化,這些更改會改善一個細粒度指標而代價就是會惡化另一個。

請注意,Navigation TimingResource Timing APIs在某些早期實現中存在錯誤; 注意異常值(負值或極大值)可能會扭曲統計資料。最後,你可能會使用像boomerang這樣的庫,而不是自己編寫。

熟悉統計基礎知識

為了能夠理解真實使用者監控(RUM)資料,你需要了解平均值和中位數之間的差異,以及什麼是百分位數

某些型別的優化可能在中位數中不可見,但可能在第90,95和99百分位數上有很大差異。一般來說,你應該避免使用平均值,因為它們可能會產生誤導,並且強烈建議考慮使用提供百分位資料和分散式分佈圖的工具。

請記住,獨立事件是獨立的 ; 你不能只對平均值或百分位數求和,並假設獲得的資料具有代表性或意義。

注意分析

正如本文開頭所提到的,分析全域性資料集可能會產生誤導。例如,你網站上的某些功能可能僅供登入使用者使用。這可能意味著登入頁面和未登入使用者的登入頁面的效能前景可能會有很大差異。

確定影響效能的主要標準,並能夠縮小分析檢視範圍以便在多種變體(登入/未登入,移動/桌面等)之間進行比較

學會使用限制

在功能強大的MacBook Pro上進行本地測試,使用光纖 + 千兆WiFi時,無論如何,你的頁面都會感覺很快。但這並不是你的使用者在一箇中端的Android裝置上使用行動網路的情況,他們也許在通勤的時候(因此網路不穩定)訪問你的網頁。

這就是在測試頁面時使用網路和CPU限制很重要的原因。(平心而論,這可能是一次令人震驚的體驗。)

你可以在你喜歡的瀏覽器(Chrome示例)中,在作業系統級別(可能使用像Fiddler這樣的代理)通過devtools啟用限制,或者在使用WebPageTest(“高階設定”皮膚)執行測試時啟用限制。網路限制在基準測試中也很有用,可以隨時間推移獲得可比較的資料。

如果你想更進一步瞭解,你可以嘗試2G Tuesday的變化,或在你的辦公室設定一個模擬慢速3G移動連線的測試WiFi。

區分延遲,頻寬和CPU

隨著新一代行動網路的安裝和升級,網際網路頻寬每年都在迅速提高,即使在發展中國家也是如此。現代4G連線可能比過時的固定電話更好 - 連線型別可能是一個誤導因素。

另一方面,由於物理限制,延遲不會快速改善。距離你的伺服器數千公里的使用者的長尾,不能做任何事情來改善他們的延遲,但通過確認問題並採取行動(最小化往返次數,識別TCP慢啟動,通過dns-prefetch/ preconnect/ preload等,預先啟動DNS / TCP / TLS /資源請求)可以顯著緩解此問題。

最後但並非最不重要的是,雖然高階移動裝置與昔日的桌上型電腦一樣強大,但低端裝置幾乎沒有改進 - 它們只是變得更便宜了,但仍然使用較慢的CPU和較小的記憶體(儘管在相同的網路條件下)。

特別是當涉及到大的JavaScript bundles時,頻寬(下載)不再是瓶頸 - CPU速度(解析和執行)才是。

瞭解HTTP / 1.1和HTTP / 2之間的區別

HTTP / 2(簡稱h2,這令HTML編寫者很困惑!)是HTTP協議的一個主要修訂版,它顯著改變了資源通過線路傳輸的方式,並且與HTTP / 1.1具有完全不同的效能特徵。HTTP / 1世界的一些“最佳實踐”(如域分片)在HTTP / 2中不再有意義,但同樣重要的是,在各種瀏覽器和伺服器中,某些HTTP / 2功能的實現是完全不同的,並且通常是不完整的

首先,在你最喜歡的devtools網路皮膚,檢查你的assets是通過HTTP / 1還是HTTP / 2提供(右鍵單擊列列表並勾選Protocol條目以使其顯示)。

如果你的應用程式使用多個域來儲存圖片,指令碼和動態資料,那麼你很可能會混合使用這兩者。一旦瞭解了這一點,請調整每個傳輸的最佳實踐。通常,你應該嘗試儘可能多地重用HTTP / 2連線 ; 瀏覽器會嘗試通過將某些請求“合併”到同一個連線中,每個瀏覽器的實現會略有不同

(請記住,大多數開發者代理 - 比如Fiddler - 預設將所有連線降級到HTTP / 1.1。確保在進行效能調查時禁用它們,以避免觀察到誤導行為。)

通常,從2018年末開始,WebPageTest提供了比瀏覽器的devtools更高階的HTTP / 2資訊,因此如果你對某些assets使用HTTP / 2,則應該花時間探索WPT瀑布流和連線檢視。

成為瀑布流檢視的朋友

WebPageTest是一個非常強大的工具,你可以從其瀑布流和連線檢視中讀取大量資訊。這是一個完整的單獨部落格文章的主題,但簡單來說,下面是你開始最能操作的資訊:

  • 瀑布流的形狀(越“垂直”越好),
  • “網路靜默”的縫隙,
  • 關鍵資源的DNS,TCP,TLS的請求延時--- preconnectdns-prefetch是直接候選解決方案

瞭解瀑布流對於進行非凡的優化至關重要。你可以從這個關於瀑布流反模式的演示開始,然後通過自由探索逐漸深入探討這個主題。

保持JavaScript不受影響

向客戶端傳送大量JavaScript程式碼是現代Web最重要的問題之一。 評估JavaScript非常昂貴 - 遠遠超過渲染大小相當的影象。當你遇到一個大型的現有專案時,要做很多的效能優化並不總是那麼容易。話雖如此,這裡有一些小技巧:

  • 使用Chrome開發工具中的coverage選項卡查詢未使用的JavaScript和CSS。
  • 檢視你使用的庫並尋找更小的替代品。Bundlephobia非常適合用來進行npm artifacts比較。
  • 確保不要匯入大型庫而是隻使用它提供的一些小功能。實際上,你可能根本不需要某些庫; 現代JavaScript非常強大,而且polyfilling的選擇比以往更容易
  • 更新依賴關係也可能會減少你的包大小(或者恰恰相反 - 請小心),有時是間接的 - 通過避免專案中重複的傳遞子依賴關係。

瞭解你的構建工具

像webpack這樣的打包工具有很多配置選項可以幫助提高效能。閱讀文件並完善配置可能需要一段時間,但這是一項很好的投資,可能帶來很高的回報。特別是,code splitting是一種關鍵技術,可以最大限度地減少初始JavaScript有效負載並在載入時保持頁面響應。

如果你正在使用babel來轉換ES2015 +程式碼,請確保根據你的瀏覽器支援級別使用並正確配置babel-preset-env,以避免在最終打包中進行不必要的轉換和polyfill。

歸功於打包工具的tree-shaking(死程式碼消除)功能,將依賴項更新到較新的基於ES2015 +的版本可以使你的包更小。

考慮長期快取

HTTP / 1世界的“常識”是將給定頁面上所需的所有JavaScript合併為單個檔案。如果你只進行一次頁面部署並且永遠不會再更改它了,這是合理的。但是,如果你定期更新部署,並且某些模組的更改頻率高於其他模組,則將它們拆分為單獨的包可能更有用,即使它們總是一起使用也是如此。

當使用HTTP / 2並且保持合理的打包數量時,多次下載的首次微小的延遲對於回訪者增加的快取命中率(因此避免昂貴的網路請求)來說,支付的代價很小。

獲得正確的長期快取需要可以進行重複構建,對舊版本的webpack來說很難,甚至是webpack 4。剛剛釋出的(alpha版)webpack 5承諾將開箱即用的長期快取作為核心功能,這是一個非常好的訊息。

使用開發人員版本的Web瀏覽器

現在的Firefox(Beta / Dev Edition / Nightly),Chrome(Beta / Dev / Canary),Safari(技術預覽版)的預發行版本非常穩定。他們在部署到終端使用者之前提供新的Web平臺功能和重要更改的預覽,還提供了有關棄用功能的早期警告,並且在新增到主流版本數週/月之前通常會在在開發工具中提供顯著的改進

懂得權衡利弊

改進一個指標有時意味著另一個指標的惡化; 在瀏覽器X中改進的可能在瀏覽器Y中產生回退。

提前考慮,定期測試所有主要的瀏覽器引擎,並確保保持平衡。在分析工具中建立檢視或過濾器,以便能夠快速隔離來自不同瀏覽器,不同國家/地區的統計資訊等。部署重大更改時,請務必分別檢查每個檢視。

信任但要驗證

警惕提供銀彈,卻不提及任何缺點的部落格文章。始終測試多種瀏覽器和裝置型別。

例如,<link rel=preload>如果使用得當並且符合你的需求的話,它是一個很好的功能,但是如果使用不當,它實際上可能會過度優先處理某些請求導致效能下降,從而犧牲了更重要的請求。

另一個例子:<script type="module">/ <script nomodule>是一種很有前途的模式,用於將現代JavaScript傳輸到現代瀏覽器並將ES5轉換為傳統的JS,但它會在某些瀏覽器中產生重複請求

請記住,一種方法不能解決所有問題

對高頻寬網路使用者有利的事情 - 例如預載入(prefetching) - 對於資料套餐有限或頻寬有限的使用者(發展中國家,資料漫遊使用者)並不總是有利。網路資訊API,客戶端提示,通過service worker重寫動態請求可能有助於緩解這些問題。

效能是一個動態的目標

你的網站不是孤立的。瀏覽器會更新並且速度更快(但有時更慢),使用者會更換他們的裝置,移動和固定電話網路也會升級 - 在分析長期效能KPI時請記住這一點。

你的網站的受眾特徵也會隨著在新的國家/地區受到歡迎而發生變化,在極端情況下,當你實現真正的大規模改進時,你的全域性指標可能會更糟!

記錄你學到的東西

快速學習太多東西時很容易迷失。記錄你發現的新東西,為有用的URL等新增書籤,以便以後回顧。在issue tracker中開啟tickets以進一步研究一些想法也可能起到一些作用。

聯絡社群

perf社群並不大,但如果你遇到困難,你可以在WebPageTest論壇上依靠那些熱心人士提供的幫助。Twitter也可能是一個很好的資訊來源。

持續學習並保持輸出,一次一件事

理解Web效能的複雜性需要時間,即使具備了所有知識,找到正確的執行方案有可能很困難。有時你只需要擼起袖子加油幹,然後反覆試驗和試錯。

目前還沒有人發現效能銀彈。學習新事物,提出想法,嘗試,測量,權衡利弊,部署改進 --- 一次一個。

享受你(網站)的效能之旅!

附加資源

感謝Hine Courtenay為本文的草稿版本提供了大量修正,以及Doug Sillars提供的有用技巧。

相關文章