from 前端早讀課2020-05-21https://mp.weixin.qq.com/s/I8DYY4oY_uJ_6IpIQNLSYQ
一、簡介
Lighthouse 是一個開源的自動化工具,用於改進網絡應用的質量。只要為 Lighthouse 提供一個需要審查的網址,它將針對此頁面運行一連串的測試,然后生成一個有關頁面性能的報告。
二、使用方式
目前官方提供了4種使用方式:https://github.com/GoogleChrome/lighthouse
-
Chrome 開發者工具(DevTools)
-
Chrome 擴展
- Node Module
-
Node CLI
安裝:
npm i -g lighthouse
測試:
lighthouse https://webpack.js.org/plugins/provide-plugin/
結果:


lighthouse測試流程圖如下:

-
- Lighthouse 與瀏覽器建立連接。
- 測試的初始化配置與加載待測試頁面。
- 在頁面加載過程中,運行一系列的采集器(gatherers),每個采集器都會收集自己的目標信息,並生成中間產物(artifacts)。
- 運行一系列的審計項(audits),每個審計項都會從中間產物(artifacts)中獲取所需的數據,計算出各自的評分。
- 輸出report
- 生成的.html文件

Lighthouse 6.0 的報告引入了 3 個新的指標,其中兩個 LCP 和 CLS 來自 5 月份新發布的 Core Web Vitals 衡量體系,另一個是 TBT。
-
Largest Contentful Paint(LCP)
主內容渲染時間,是前 FCP 指標的一個有力補充,LCP 分數低於 2.5 秒會被認為是“好”的體驗。
-
Cumlative Layout Shift(CLS)
累計布局變更/累計視覺變更,用來計算非預期的 UI 界面變更對用戶操作的影響,CLS分數低於 0.10 被認為是“好”的體驗。
-
Total Blocking Time(TBT)
總阻塞時間。用來量化加載的響應能力,累積主線程被阻塞並會影響用戶操作反饋的總時間。TBT 也與 Core Web Vitals 中的 FID 指標相關聯(First Input Delay 首次交互延遲)。
隨着衡量指標的更新,評分規則也必然做出相應調整,具體如下圖所示:

-
TTI 的權重從 33% 下降到 15%,這個主要基於 TTI 反饋的穩定性不夠以及新的補充指標 TBT 的加入。
-
FCP 的權重從 23% 下降到 15%,主要是新的補充指標 LCP 的加入。
-
最大可能 FID 指標被廢棄,不會再暫時到報告中,現在更推薦通過TBT 指標來衡量可交互性。
-
首次有效渲染(First Meaningful Paint)被廢棄,這個數據太不穩定且因為 Chrome 內部渲染機制的關系而無法標准化。
-
首次 CPU 空閑 被廢棄,因為這個指標和 TTI 指標重復性較高,而后續更推薦使用 TBT 和 TTI 指標來衡量交互性。
-
CLS 指標的權重目前還相對較低,在后續的主版本更新中可能會將其調高。
三、LightHouse各個模塊

1. Driver模塊
Chrome 瀏覽器在啟動的時候,可以通過 --remote-debugging-port 參數設置遠程調試端口,如以下命令可以打開 Chrome 並設置遠程調試端口為9222。
chrome.exe --remote-debugging-port=9222
之后就可以使用地址 http://localhost:9222 進行遠程調試了,比如以下命令可以讓 Chrome 瀏覽器打開一個新的 Tab。
curl http://localhost:9222/json/new
與瀏覽器通訊
Driver 模塊的 Connection 實例(負責與瀏覽器進行通信),該實例在初始化的時候,正是通過調用遠程調試端口的/json/new指令打開一個新的 Tab,並使用返回的 webSocketDebuggerUrl 與瀏覽器建立 WebSocket 連接,之后就可以進行雙向通信。

雙方建立 WebSocket 連接后,必須使用Chrome DevTools Protocol進行通訊。該協議以 JSON 為格式,定義指令的方法名與參數。

Lighthouse 通過 Chrome DevTools Protocol 定義的主動指令與事件通知,就實現了操控 Chrome 瀏覽器,並且感知頁面加載過程中的各個事件。
日志記錄

Driver 模塊中的另外2個重要實例是 DevtoolsLog、NetworkRecorder,他們用於將瀏覽器發出的通知事件進行結構化的存儲。其中 DevtoolsLog 會記錄各個領域的全量日志,NetworkRecorder 只存儲網絡相關日志,並會分析出當前網絡請求狀態(繁忙、空閑)等。
模擬器
emulation模塊的作用是模擬測試設備,如模擬 移動端 / PC 端、屏幕的尺寸,模擬設備的 UserAgent、Cookie、網絡限速等。

2.Gatherer 模塊
該模塊的一個重要概念是 pass:控制頁面如何加載,並通過配置gathers決定在頁面加載過程中采集哪些信息。
// 一個pass的配置 { passes:[{ passName: 'defaultPass', recordTrace:true,// 是否記錄Trace信息 useThrottling:true,// 是否使用限速 gatherers:[ // gatherers列表 'css-usage', 'viewport-dimensions', 'runtime-exceptions', 'console-messages', 'anchor-elements', 'image-elements', 'link-elements', 'meta-elements', 'script-elements', 'iframe-elements', ... // 省略 ], }, ... // 省略 }
其中,gathers中每一個 gatherer,在代碼倉庫中都有與之對應的同名實現文件,並且都繼承自相同的父類 Gatherer,其中定義了三個模板方法,子類只需實現模板方法即可。
Class Gather { // 在頁面導航前 beforePass (passContext) { } // 在頁面loaded后 pass (passContext) { } // 在頁面加載完畢,且trace信息收集完畢后 afterPass (passContext, loadData) { } }
當 pass 中定義的所有 gatherers 運行完后,就會生成一個中間產物 artifacts,此后 Lighthouse 就可以斷開與瀏覽器的連接,只使用 artifacts 進行后續的分析。
3. Audits 模塊
與 gatherers 類似,在配置文件中也會定義需要運行的 audits,每一個 audits 也都有與之對應的同名實現文件。
{ audits:[ 'errors-in-console', 'metrics/first-contentful-paint', 'metrics/first-meaningful-paint', 'metrics/speed-index', 'metrics/first-cpu-idle', 'metrics/interactive', 'screenshot-thumbnails', 'final-screenshot', // 省略 ], // 省略 }
在每個 audit 中都會定義一個靜態方法meta(),對該 audit 進行描述,並聲明所需的 artifacts,ErrorLogs 這項 audit 就聲明了其需要上文提到的 RuntimeExceptions 所生成的中間產物。
class ErrorLogs extends Audit { static get meta (){ return { id:'errors-in-console', title: str_(UIStrings.title), failureTitle: str_(UIStrings.failureTitle), description: str_(UIStrings.description), requiredArtifacts: ['ConsoleMessages', 'RuntimeExceptions'],
}; } }
Audit 實例需要實現的另一個模板方法是audit(),在該方法中可以拿到所需的中間產物,並基於中間產物計算出本項 audit 的得分與詳情。
class PageTitle extends Audit { static get meta() { return { id: 'page-title', title: 'title of page document', failureTitle: 'Does not have page title', description: 'This audit get document.title when page loaded', requiredArtifacts: ['PageTitle'], }; } static audit(artifacts) { return { score: artifacts.PageTitle ? 1 : 0, displayValue: artifacts.PageTitle || 'none' }; } }
4. Report 模塊
在配置文件中,會定義每個測試類別所需的審計項,以及每個審計項所占的權重。如下所示的為性能(performance)這項測試類別所需的審計項:
{ 'performance': { title: str_(UIStrings.performanceCategoryTitle), auditRefs: [ {id: 'first-contentful-paint', weight: 3, group: 'metrics'}, {id: 'first-meaningful-paint', weight: 1, group: 'metrics'}, {id: 'speed-index', weight: 4, group: 'metrics'}, {id: 'interactive', weight: 5, group: 'metrics'}, {id: 'first-cpu-idle', weight: 2, group: 'metrics'}, {id: 'max-potential-fid', weight: 0, group: 'metrics'}, // 省略 ] }, }
在最終匯總階段,Lighthouse 會根據該配置文件以及前一個環節中計算出的每個審計項的評分,加權計算出 performance 的評分。
並基於每個審計項的評分與種類,將審計項划分為通過與不通過,對於不通過的審計項會給出詳細的測試詳情與優化指引。
四、限速模擬
由於頁面性能受宿主機網絡與 CPU 頻率等參數的影響較大,Lighthouse 提供了三種方式供模擬較差的宿主機網絡環境。其背后的邏輯是,如果頁面能夠在較差的環境下達到一個較好的測試分數、那么大部分用戶對頁面的直觀感受都會較好。
Chrome Devtools 的 Audits 面板中,可以看到三種限速方式:

- simulated: 即限速是模擬的(加載頁面時不進行限速,加載完頁面后,模擬計算出在限速條件下的性能指標值),所以可以在較快的速度下地完成審計並有相似的測試精度。
- applied: 即通過 DevTools 進行限速,頁面是在一個真實受限的網絡與降速 CPU 條件下加載的。
- no throttling: 即 Lighthouse 不進行額外的限速,通常在不進行性能測試、或開發者自行對宿主機進行限速時使用該項。
在三種限速方式中,Lighthouse 真正對網絡與 CPU 進行限速的只有 devtools 這種限速方式,實現的方式是通過上文提到的 Driver 模塊發送對應領域的指令給 Chrome 瀏覽器。
五、補充
1. 在上文介紹 pass 時,我們提到其中有一個參數用來控制是否收集 Trace 信息。Trace 信息的可視化展示就在 Chrome devtools 中 Performance 面板:

當 pass 中配置了開啟收集 Trace 信息時,Lighthouse 在頁面加載完畢后,就可以拿到完整的 Trace 信息, 從中可以知道頁面加載時的 FCP 等關鍵渲染節點。
