本文通過分析 Chrome 的 DevTools 的技術實作,特别是在浏覽器核心中的實作部分,來展示這款被萬千開發者所喜愛的開發工具背後的秘密。本文适合閱讀對象主要有前端開發者、有志于開發 Hybrid 應用調試工具或重寫 webdriver 實作對 Chrome 或 WebView 控制的應用工程師。
從 2008 年 Google 釋放出第一版的 Chrome 後,整個 Web 開發領域仿佛被注入了一股新鮮血液,漸漸打破了 IE 一家獨大的時代。Chrome 和 Firefox 是 W3C Web 标準的堅定支援者,随着這兩款開源浏覽器市場佔有率逐漸加大,迎來了開發者的春天。這就迎來了一個新的職業分工——前端工程師 frontend-engineer,前端工程師促進了 Web 應用的繁榮,功能強大的調試工具必不可少。Google 基于開源的基礎上順勢推出了 DevTools,廣受網頁開發者的好評,随即也推動了 Chrome 的在商業的成功。
注:本文所有代碼分析,基于 Android Chromium 87.0.4280.141 版本分析而成。由于筆者所在團隊主要從事 Android 平台的 Blink 核心開發,是以分析過程主要集中在移動端,其他平台隻是資料通路的差別,實作原理差别不大。
2006 年之前,這屬于 IE 時代,在 IE 時代編寫 JavaScript 代碼時的調試手段,主要靠 window.alert() 或将調試資訊輸出到網頁上來分析邏輯 bug。這種硬 debug 的手段,不亞于系統底層開發,往往一個小問題要花費掉一整天時間,開發效率極低。
2006 年 1 月份,Apple 的 WebKit 團隊釋放出第一版本的 Web Inspector,此版本功能還比較簡樸,僅可以檢視 DOM 節點的繼承關系,節點所應用了哪些 CSS 的規則。但此版本已經奠定了今後多年的網頁調試工具的原型,具有劃時代意義。

WebKit 團隊的疊代速度非常快,2006 年 6 月釋出了一個重量級功能,JavaScript 的斷點調試功能,此時已經具備開發者神器的雛形。
同時開源陣營出現一款 Firefox 的插件 Firebug,專注于 Web 開發的調試,奠定了現代 DevTools 的 Web UI 的布局。早期版本就支援了 JavaScript 的調試,CSS Box 模型可視化展示,支援 HTTP Archive 的性能分析等優秀特性,後來的 DevTools 參考了此插件的功能和産品定位。2016 年 Firebug 整合到 Firefox 内置調試工具,2017 年 Firebug 停止更新,一代神器就此謝幕。
此時迎來了一個開源界的狠角色 Google 團隊,基于 WebKit 加入浏覽器研發,推出的 Chrome 以「安全、極速、更穩定」吸引了不少 IT 極客的關注,同時開發者工具這方面, Google 吸收多款調試工具的優秀功能,推出了今天的主角 DevTools。
早期版本現在看起來這個布局有點簡陋,但這可是十幾年前的作品。支援 DOM + CSS 檢視,檢視資源加載分析,腳本調試以及性能調試。現在開發中常用 DevTools 的功能,基本也就這幾個功能。
那個年代的 DevTools,基本是在跟随 Firebug 的功能,隻是互動方式上的差異。2007 年 Steve Jobs 釋出了第一代 iPhone 手機,Google 相繼推出了 Android 手機,網際網路的發展來到移動網際網路時代。DevTools 此時開始超越同類工具,支援了遠端真機調試。Chrome 是多程序架構,DOM 和 JavaScript 是運作在子程序中的,是以 DevTools 的底層實作,已與同類産品完全不同。Chrome 的架構師将 DevTools 實作架構調成在 client-server 模式,這個架構讓遠端真機調試成為可能。為了友善網絡資料傳輸,Chrome 設計出了一套資料封裝協定 Chrome DevTools Protocal(CDP),接下來的幾年,這個架構的調整在開源世界大放異彩。
yan Dahl 基于 Chromium 的 JavaScript 虛拟機 V8 設計了 Node.js,Node.js 的面世讓 JavaScript 這款 Web 腳本語言走出了浏覽器,打開了服務端程式設計、桌面程式設計可以使用 JavaScript 語言的新局面。依托于 DevTools 的 client-server 架構以及 Node.js 的開發者的數量不斷增加,DevTools 也迅速出圈,Chrome 團隊于 2016 年開始支援 Node.js 的調試。DevTools 已從一款 Web 調試工具,演變成 JavaScript 生态中重要一員,助力更多的開發者開發更多優秀代碼。Node.js 的生态都離不開 DevTools ,比如桌面開發架構 Electron、開發者喜愛的編輯器 Visual Studio Code 、前端架構 Vue.js、Facebook 開源 Android 性能分析工具 Stetho等。
DevTools 是 client-server 架構,client 就是使用者操作的 Web UI 界面,負責接收使用者操作指令,然後将操作指令發往浏覽器核心或 Node.js 中進行處理,并将處理結果資料展示在 Web UI 上。server 啟動了兩類服務,一種 HTTP 服務;另一種 WebSocket 服務。
HTTP 服務提供核心資訊查詢能力。比如擷取核心版本、擷取調試頁的清單、啟動或關閉調試。 WebSocket 服務提供與核心進行真實資料通信的能力,負責 Web UI 傳遞過來的所有操作指令的分發和處理,并将結果送回 Web UI 進行展示。
下圖展示出了 Android DevTools 的整體架構圖,從左側開發者通過 Web UI 的發起的操作指令,是怎麼一步一步地将操作指令,傳遞到手機中的 Browser Core(Browser Core 運作 Chrome 浏覽器核心的應用,比如 Chrome 浏覽器、Android WebView、NodeJs 應用等)中執行的過程。
Android 平台巧妙地使用 ADB forward 能力,解決了 PC 上的 WebUI 與 Android 手機中的 Chrome 核心的連接配接問題。輕松了實作了遠端調試的能力,不要小瞧這一實作,這對前端開發者效率提升是極大的。因為前端開發者的工作環境,目前來看基本是在 PC (Windows、Mac、Linux 統稱為 PC)下,通過遠端調試能力的實作,讓移動端的開發實作了所見即所得。
正是 Chrome 團隊基于網絡通信方式,作為 DevTools 底層通信架構,才為後來的 Web 開發團隊百花齊放奠定了基礎。TCP/IP 是網際網路的基礎,沒有哪種語言或平台不支援 TCP/IP 的。DevTools 選型 TCP/IP 方式直接抹平了不同平台或系統架構之間的差異。
Chrome DevTools Protocol(簡稱CDP) 這組開放協定的推出,再一次将 DevTools 的實作,真正做到了跨平台。CDP 本質就是一組 JSON 格式的資料封裝協定,JSON 是輕量的文本交換協定,可以被任何平台任何語言進行解析。正因為此,官方推薦的支援 CDP 的語言庫多達近十種。Google 官方推薦了 Node.js 版本 Puppeteer ,通過 Puppeteer 完整地實作了 CDP 協定,為 Chrome 核心通信的方式打了一個樣,接着開源世界陸續推出了多個語言版本的 CDP 的使用庫。關于 CDP 協定,在稍後的章節會詳細介紹。
Chrome 的架構師通過高度抽象能力,将 DevTools 的底層架構抽象成 TCP/IP 和 CDP 兩個部分,奠定了 DevTools 的跨平台跨終端的能力。當年 WebSocket 的實作方案還處在草案階段,Chrome 架構師就大膽地采用 WebSocket 實作了調試協定中的主協定部分。現在看來,開發者日常使用的頁面的實時截圖能力,可以實時觀察到遠端網頁中所展示的界面,這個實時性就是基于 WebSocket 來提供的。筆者還很佩服 Chrome 架構師的眼光和設計氣場,正是他們優秀的能力,将網頁開發者工具帶到新高度。
Chrome DevTools Protocol(簡稱CDP)此協定包含兩部分 HTTP 和 WebSocket,DevTools 的 Web UI 将控制指令發往浏覽器核心,其中的控制指令、參數以及傳回值,都是通過 CDP 來進行封裝。指令的發送時,由 Web UI 進行封裝後,通過 WebSocket 發往浏覽器核心。接收到浏覽器核心回報回結果後,再按協定進行解包,分發給Web UI。
為了分析 Web UI 與 Android 浏覽器核心通信過程,需要做一下環境準備。
為了能通路到核心中資料,浏覽器核心需要開啟 DevTools Server ,PC Chrome 和 Android Chrome / WebView 的開啟方式略有不同。
PC Chrome 啟動時,增加一個啟動參數 -remote-debugging-port=9222 , 這樣 DevTools Server 就會偵聽本地的端口,可以向 http://localhost:9222 發起 HTTP / WebSocket 請求,即可擷取 DevTools 中的資料。
對于 Android Chrome 與 WebView 略有差異,由于 WebView 預設是不開啟調試功能的,需要在用戶端手動開啟,才能啟動 Server。
此時 Android Chrome / WebView 在手機内已啟動了 Server,但為了在 PC 上能夠通路到,需要使用 ADB工具的端口轉發能力。
Android Chrome / WebView 使用 unix domain socket 建立的 Server 端,此 socket 的連接配接符為:
chrome_devtools_remote和 webview_devtools_remote_分别為 chrome 和 WebView 的連接配接符。WebView 的連接配接由于可能不同應用都使用了 WebView,是以采用了程序 ID(PID)作為字尾來區分。
通過 ADB forward ,将 PC 與 Android 裝置通路打通,執行如下指令:
至此,就可以在 PC 上通過 9222 來通路 Android 裝置中的調試頁面了。
從上面傳回值,可以得到如下幾個資訊:
Android-Package,使用 WebView 應用的包名。
Browser,核心的版本号。
Protocol-Version,為 CDP 的協定版本,目前版本為 1.3,從 1.0 開始,還有 1.1、1.2 等。
User-Agent,浏覽器的 UA 資訊。
V8-Version,所使用的 JavaScript 引擎版本号。
WebKit-Version,由于 Blink 核心是基于 WebKit 537.36 版本開發,是以會有此版本資訊。
webSocketDebuggerUrl,這是 WebSocket 的調試 URL。
傳回了一個 JSON 的數組,每一個調試頁占用一個資料元素,上面的傳回值可以看出,筆者環境下 vivo 浏覽器打開了兩個頁面,一個 https://xw.qq.com/#news 和 about:blank。
description,是個 JSON 對象,展示目前頁面的狀态資訊。比如頁面寬、高、在螢幕上的偏移,WebView 是否已經 attached 到 view 上了,隻有 attach 上的頁面,才會被展示出來,能否被調試。
devtoolsFrontendUrl,此值為一個 URL,就是日常使用 DevTools 的 WebUI 控制台位址,這是個 Web APP 當通路過一次後,會就緩存一份在浏覽器下。此頁面托管在某個在國内無法正常通路位址,是以經常會出現打不開面闆,而顯示白屏的情況。Chrome 浏覽器在打包時會内置一份與目前核心比對的 WebUI 版本,是以 Chrome 可以直接調試自己的頁面。
id,這是每個打開頁面随機生成的 GUID 值,用于生成 WebSocket 連結,以區分不同頁面。
title,打開網頁的标題,對應網頁 head 中的 title 标簽内容。
type,頁面的類型,主要有以下幾類 page、iframe、worker 以及 service_worker 等。
URL,目前打開的頁面 URL。
webSocketDebuggerUrl,此參數為 WebSocket 連接配接的 URL。
HTTP 協定還有其他幾個子指令,比如 protocol、new、activate 等,主要是頁面控制類的,就不一一介紹了。
WebSocket 協定由四部分組成: Domain 、Method 、 Event 和 Type 。
1)Domain,命名空間,類似 C++/Java 中的命名空間或包名,用于分割不同的指令。用于将衆多子指令按類劃分,友善使用者調用,以及防止 Method 同名沖突。以 1.3 版本的 CDP 協定,一共劃分出 15 個Domain。
Browser: 用于管理浏覽器對象。
Debugger: 用于調試 JavaScript 的分類,比如斷點、調用棧等。
DOM: 所有 DOM 節點操作都在此 Domain 下,DOM 節點的修改,周遊等。
DOMDebugger: 管理 DOM 節點調試的 Domain,DevTools 中節點修改斷點,就是通過這組 Domain 中提供的 Method 完成的。
Emulation: 此是一組環境模拟器集合,DevTools 中的修改裝置尺寸、UserAgent 等是由這個 Domain 實作。
Input: 事件分發方法的集合。
IO: I/O 流操作集合。
Log: Log 控制 Method 集合。
Network: 浏覽器網絡通信資料,可能通過此 Domain 進行捕獲。
Page: 基于 Blink 中的 Page 操作 Method 集合,比如重新整理,打開 URL。
Performance: 內建了性能分析 Method。
Profiler: 采樣分析器的 Method 內建在此 Domain 下。
Runtime: 與 JavaScript 通信的 Method 被內建此 Domain 下,比如執行 JavaScript 代碼。
Security: 安全類操作,比如證書錯誤。
Target: DevTools 連接配接的一些控制類 Method 在此 Domain 下。
2)Method,方法名稱,每個 Domain 下都會有一組 Method,指明了具體操作浏覽器核心的功能。有三部分組成:名稱 、 參數 和 傳回值 。與 C++/Java 中方法描述一緻。
名稱:Debugger.setBreakpointByUrl;
參數:lineNumber integer [,url string,urlRegex string,scriptHash string,columnNumber integer,condition string ];
傳回值:breakpointId BreakpointId,actualLocation Location。
3)Event,通知事件,網頁會有很多狀态通知,需要同步到 WebUI 或其他控制端上來。Event 就是用于通知這些事件的。比如 DOM 屬性發生了變化時,将會收到 Dom.attributeModified 事件;将 JavaScript 傳遞到核心去執行時,将會收到核心發回來的 Debugger.scriptParsed 事件和參數,參數如下:
4)Type,是 Method 或 Event 傳遞參數的複雜資料類型,這些類型與核心的對象相對應。比如 DOM.Node 類型就對應着 Blink 中的 DOM 節點。主要屬性如下:
nodeId: NodeId 也是 Type,節點 id,根據此值可以在核心找到對應的節點。
parentId: NodeId 也是 Type,父節點 id 。
nodeType: integer,節點類型。
nodeName: string,節點名稱。
nodeValue:string, 節點内容。
children: array,子節點數組。
attributes: array, 節點屬性數組 通過 Node 上這些屬性,就可以将 DOM 樹的節點在記憶體占用描述出來。DevTools 的 Web UI 中 Element 面闆,就是通過 DOM.getDocument Method 将一棵 DOM 樹展現出來。
通過 CDP 的這種資料組織方式,既可以傳遞控制指令來操作核心,也可以接收核心狀态通知(Event)。通過 CDP 可以讓浏覽器做任何事情,而且得到的資訊遠比使用 Chrome 圖形界面還要多。是以, Google 推出 Chrome Headless 版本,被廣泛應用于 web 自動化測試、網頁爬蟲以及網頁沙箱等領域。
當調試移動端浏覽器時,可以實時看到移動裝置上的所浏覽的螢幕,這是怎麼做到的呢?
其實,就是一張一張截圖通過 Page.screencastFrame 事件将 base64 後的圖檔發回到 Web UI 中展示的。
從 Page.screencastFrame 通知事件帶回了圖檔和描述資訊(Meta data):
通過描述資訊,即可将此圖檔的資訊展示在 WebUI 上。一張截圖近 1M 的大小,由于 DevTools 利用了 WebSocket 的雙向長連結的特性,是以展示出來無比平滑和清晰。
以上章節,介紹了從 Web 開發者的角度出發,将操作指令傳遞到移動端 Browser Core 的一個整體流程,以及 CDP 通信協定相關内容。本節重點介紹在 Browser Core 中的實作過程,先介紹 DevTools 在浏覽器核心中實作,後面筆者會挑選 JavaScript 如何從字元串傳遞到 V8 中執行過程,展開來進行詳細介紹,這一行為的實作方案。
DevTools 以啟動一個 Web Server 為起點,然後将調用指令發到相應處理子產品,整體架構圖如下:
DevTools 在核心中大體上分為四層:
Server 層,用于接收外部網絡發過來的操作請求。
Agent 層,對于 Server 層發過來的請求,進行拆解,根據操作的類型不同,再分發給不同的 Agent 來處理。
Session 層,Session 是對不同的業務子產品進行了一層抽象。過了 Session 層後,将會進入不同的業務子產品,可以到達 V8, Blink 等。
業務層,就是具體的功能子產品,比如 V8 子產品,主要負責 JavaScript 的調試相關能力的支撐。
Server 層由 DevToolsManager 這個單例對象來管理,由于是單例是以一個程序隻會存在一個 Manger 對象,進而防止被重複建立出多個,導緻狀态錯亂。
Server 收到的請求都會分發給 DevToolsHttpHandler 類,此類負責網絡 Client 發過來的資料請求響應和将處理結果發送回網絡 Client, 此類有兩個重要方法 OnJsonRequest 和 OnWebSocketMessage ,分别用來處理 HTTP 協定和 WebSocket 協定。
DevToolsHttpHandler::OnJsonRequest 用于響應 HTTP 請求,用于查詢核心狀态,比如核心版本、目前支援協定,将傳回完整協定内容,友善開發者适配對應的支援。
DevToolsHttpHandler::OnWebSocketRequest 用于接收 WebSocket 的連接配接,根據此方法對不同的 Agent 對象進行了建立。
DevToolsHttpHandler::OnWebSocketMessage 所有調試請求資料,都經過此接口通過 Client 分發到不同的 Agent 上去。
Server 層資料響應時通過上面的三個接口來達到資料接收和分發的能力。
V8 JavaScript 引擎用于解釋執行網頁中的 JavaScript 腳本,同時也可以通過 DevTools 接收外部傳遞過來的腳本,腳本在目前網頁的 Context 下執行,是以可以通過 JavaScript 來操作網頁行為,比如修改 DOM 節點屬性。CDP 中設計了執行 JavaScript 接口 Runtime.evaluate ,引方法的參數如下:
其中,最重要的一個參數就是 expression ,此為一個 string 類型的參數,用于存放需要執行的腳本内容。上例将會在網頁中彈出一個内容為 hi 的 alert 确認框。
V8 中有個專門的子產品,V8RuntimeAgentImpl 用于支援 CDP 中 Runtime 的這個 Domain,當然也有 V8DebuggerAgentImpl 是用來支援 Debug 這個 Domain 的具體實作。V8RuntimeAgentImpl 中 evaluate 方法,就是用于負責接收 DevTools 發過來的執行請求。
V8RuntimeAgentImpl::evaluate 會啟動一個 microtasks 來執行腳本,最終會走到 v8::internal::Execution::Call 中,Execution 子產品會負責将腳本進行文法解析和編譯成位元組碼,最終排程到虛拟機器中運作。
執行流程如上圖所示,Web UI 發出執行腳本的字元串,WebSocket 的 OnWebSocketMessage 将會收到此指令,然後通過 DevToolsSession 逐層向 V8 分發。由于 Chrome 是多程序架構,分為Browser 程序和 Render 程序,之間通過 IPC 進行通信。上圖左側在 Browser 端執行流程,右側為 Render 端執行流程。
Render 端的DevToolsSession::DispatchProtocolCommand 是一個重要的分發接口,是以發到 V8 或 Blink 的控制指令,都會經過此接口。接着就會将控制指令發送到 V8RuntimeAgentImpl,根據指令功能的不同,排程到不同功能子產品進行處理。
DevTools 提供一組功能強大的性能分析工具,網絡、JavaScript 調試、渲染、記憶體以及标準支援度檢測等。下面介紹 Performance 面闆中一些性能分析時的一些功能。主界面被劃分為這幾塊:
1)幀率(FPS):線性展示了做 Performance 期間,網頁渲染的幀率。
2)CPU 使用率:CPU 占用走勢圖
3)加載過程中截屏:定時采集了網頁截屏性能
4)網絡加載時序:展示網絡資源加載次序及耗時情況
5)幀耗時(Frames):展示了渲染每幀耗時情況,紅色表示存在耗時較長的幀。
6)Web Vitals 名額:Google 推薦一套性能體驗名額,下面會詳細介紹。
7)核心中主要線程:浏覽器核心中存在多個線程各有分工,當出現耗時較長幀時,需要在這些線程中排查,具體哪個線程在耗時。主要分為這幾個:
Main,這是 Blink 主線程,負責網頁的排版、解析、JavaScript 執行等。
Raster,光栅化線程,用于将渲染對象轉化成 Bitmap。
GPU,硬體加速渲染線程,将 Texture 繪制到螢幕上。
Chrome_ChildIOThread,負責網絡資源,檔案操作。
Compositor,合成線程,負責将渲染時各個層,合成在一起然後進行光栅化。
ThreadPoolForegoundWorker,Worker 的工作線程池。
8)資訊面闆:用于展示選擇子產品詳細資訊,幾個名額含義:
Loading:網絡請求和 HTML 解析耗時。
Scripting:JavaSript 解析、編譯、在虛拟機中執行,以及 GC 耗時。
Rendering:Blink 排版渲染耗時。
Painting:繪制耗時,主要包含繪制、合成、圖檔解碼以及上屏。
System 和 Idle:是系統排程和空閑耗時。
性能分析基本思路從問題入手,網頁常見性能問題,筆者遇到的主要有這幾種情形。
需要的資源沒有及時被請求回來。排除伺服器問題,資源請求發起太晚?資源太大?
網頁分層太多,導緻 Rendering 和 Painting 時間過長。
記憶體占用過多,頁面過于複雜、資源多且大、JavaScript 大塊資源持有生命周期太長。
動畫多且消失後未移除。JavaScript 的輪播動畫、CSS 的動畫、帶有動畫的圖檔資源,比如 GIF, SVG、WebP 等。
事件偵聽不合理。事件偵聽過多且可能被高頻觸達,比如節點變化、Move 事件等。
總的來說,不論是網頁性能優化還是 Native 程式優化,隻要協調好這兩個資源占用即可:CPU + 記憶體。隻要挖掘出問題點,性能問題都會迎刃而解,問題點的挖掘除了源碼級别的審查,DevTools 可以助一臂之力。
針對上面總結的正常場景,利用 DevTools 性能分析能力,先整體上審視 Profile 圖。
網絡請求次序和時長是否合理; Main Thread 的長任務是否合理。
從 Network 闆塊觀察資源請求發起的順序,是否存在長耗時任務,阻塞着首屏展示資源加載,如果不保證需要的及時加載,就會長時間白屏。
資源問題就緒後,就需要排查哪些長耗時任務執行。先檢視 Main Thread 中的 Long task,比如,上圖的 Long task 就是 Scripting 的占了較長時間。通過 Bottom-Up / CallTree 檢視具體的耗時點,相應地優化掉。
在排查具體優化點時,有個小技巧。通常開發環境都是在 PC 上進行模拟,當版本出去後,才能暴露出問題。由于移動裝置的碎片化,很多使用者的裝置,性能可能并不好。那如何在開發環境優化這類低配置機器上的表現呢?DevTools 提供了限流的模拟,可以限制網絡制式為 2G/3G,CPU 降速。
在右上角有個“設定”,展開配置項目,可以看到 Network 和 CPU 的限流選項,選擇後重新錄制一下 Profile。
上面提到,網頁層數太多,極大地影響到網頁渲染性能。“網頁層數” 是什麼意思呢?目前,浏覽器渲染引擎為了提升網頁繪制性能,繪制時會對網頁進行分層。這樣的好處就是,僅重繪修改過的層,其他層内容如果沒有變化,就不需要重新繪制,直接取上次繪制結果,進而提升繪制效率。不同的 WEB 引擎分層的政策不同,通常會将普通網頁、CSS 動畫、Canvas、WebGL、Fix 标簽等各分為一層。分層會帶來渲染效率的提升,但也會帶來記憶體的開銷,進而會影響到性能。DevTools 能否分析網頁層數嗎?可以,在上面的“設定”中有一個選項 “Enable advanced paint instrumentation(slow)” 啟用它,重新做一次性能錄制。
在 “資訊面闆” 多了一個 “Layers” 标簽,選擇後将會看到網頁分層情況。如果存在不合理的分層,可以嘗試調整方式,将分層進行合并,進而達到提升性能。
Web Vitals 是 Google 推出的一套 Web 性能與體驗兼顧的衡量标準。原先的衡量政策基本是基于 “首字” 和 “首屏” 來衡量,但從使用者角度和技術優化角度,這兩名額都存在這樣那樣的問題。是以, Google 推出了 Web Vitals 标準,并與 DevTools 進行配合,友善開發者在開發階段,就識别出 Web 的性能問題。由于标準一直随着時代的發展,不斷變化,開發者一直追着名額的變化有點吃不消,好在 Google 明确表示,目前推出的三個名額,短時間内不會變,筆者就不清楚這個短時間是多長時間。
第一個名額:Largest Contentful Paint (LCP),大面積鋪滿時間點,2.5 秒以内算優秀。主要是指有大面積的文字、圖檔被展示出來,就算達到了 LCP。
第二個名額:First Input Delay(FID),首次可響應外部輸入事件的時間點,100 ms 内算優秀。這個名額是從使用者使用角度出發,達到 FID 的時間點,意味着使用者可以操作網頁了。
第三個名額:Cumulative Layout Shift(CLS),排版跳躍名額,0.1 為優秀。在網頁加載過程中,如果出現排好版的元素,發現大面積的移動的話,這個名額就會很高。比如網頁中 img 标簽不設定寬和高,當圖檔加載完畢後,按圖檔實際大小來排版本。這樣的就會觸發網頁重新排版,從使用者角度網頁被整體向下推了一個圖檔高度,Google 認為這個體驗不好。
LCP / FID / CLS 這三個名額,本質上是從使用者視角看網頁的性能衡量名額,開發者可以看看自己作品這三個名額屬于什麼水準。
(資料來自 statcounter.com)
Chrome 憑借着自己優秀的産品特性,安全、快速以及穩定性,赢得了大批使用者青睐。從上圖 StatCounter 統計資料,可以看出 Chrome 已成為絕對的浏覽器界的一哥,理所當然地取得商業上的成功。但是 Chrome 在開源以及生态的建立,DevTools 可謂首功一件。Google 通過 DevTools 的超越競品的特性,吸引了大批前端開發者,轉到 Chrome 下開發自己的産品。早期生态産品是 Chrome 插件,Chrome Store 中的插件數量就可以看出它的成功。
當 Node.js 的問世,DevTools 首款支援 Node.js 的調試工具,推動了 Node.js 的普及。然後 DevTools 依托 Node.js 迅速出圈。另一方面,開源世界也開始反哺了 DevTools 項目,目前支援 CDP 協定的開源方案多達 10 幾種語言,常用的語言基本都支援上了。這個領域目前還在飛速發展中,期待這個領域可以有更好的發展。
DevTools Web UI 已經從 Chromium 倉庫中獨立出來,可以單獨 Clone 下來進行二次開發,Web UI 本次限于篇幅,未做實作原理分析。其實,Web UI 也是個非常優秀的 Web APP,很适合前端開發者深度研究一下。
我們從優秀開源項目中學習到的不僅是代碼實作與架構,也可以學習到更高次元的東西,比如産品思維以及工具思維,并落地到自己項目中。回顧一下網頁調試領域發展過程,從一款 JavaScript 插件,是如何演變成今天的前端開發生态,其中有很多點值得學習。
筆者所在團隊長期緻力于 Chromium 核心的研究與學習,基于其衍生出來的産品,服務我們生态使用者,為其提供優質的上網體驗。同時,我們孵化出的 Web 浏覽服務,也為生态内應用提供強大、快速、穩定的 Web 服務能力。如果您有興趣于 Web 底層技術研究,歡迎加入我們,與一群志同道合的小夥伴共同成長,同時也能服務好億級使用者。
[1] Google Chrome
[2] 10 Years of Web Inspector
[3] 10 years of Speed in Chrome
[4] Chrome DevTools
[5] Chrome DevTools Protocol protocol
[6] Web Vitals
作者:vivo 網際網路浏覽器核心團隊-Li Qingmei
分享 vivo 網際網路技術幹貨與沙龍活動,推薦最新行業動态與熱門會議。