如何用瀏覽器開發者工具 (DevTools) 定位效能相關問題?
2025年7月3日
在前端工程師的工作中,經常會遇到各種問題,可能是某段程式碼運作不如預期,也可能是某個功能雖然正常,但是效能過慢。當遇到這些問題時,能否快速定位問題,並快速解決問題,會是區分一個前端工程師資深與否的分水嶺。
先前我們在 《什麼是可觀測性(Observability)? 為什麼需要可觀測性?》 一文談到,軟體工程師在解決問題的過程中,需要有工具協助直指問題核心,才不會在茫茫大海的可能性中,花費不必要的時間去猜問題是什麼。
這個概念在前端工程領域也是一樣的,當前端工程師要解某個 bug 時,也會需要搭配對應的工具來找問題;而對前端工程師來說,最需要熟知的工具,莫過於瀏覽器的開發者工具。因此,在接下來幾期的前端主題文中,我們會來談如何善用開發者工具,定位各類問題,這期會先從效能相關的問題開始談。
為什麼要懂瀏覽器的開發者工具?
如同在用任何工具之前,比起用工具本身,了解「為什麼」要用該工具是更重要的。在使用瀏覽器的開發者工具前,也需要先了解為什麼要懂瀏覽器的開發者工具,以下讓我們用幾個情境來說明。
假如某個前端工程師,要實作一個對接後端 API 的功能,讓使用者可以新增一筆資料,新增完後要馬上顯示新資料在畫面上;但是在實際對接後,發現功能並不如預期運作。
在這個狀況下,如果不用額外的工具,該前端工程師能做的,是在自己的程式碼中找問題在哪,然後去對照後端提供的 API 串接規格,來看是否有接對該 API。或者是實際的用 cURL 來呼叫 API 確保 API 是可以呼叫的,以及傳入的引數與收到的回覆都如預期。
但上面這個做法顯然會花很多時間,一個更快速找問題的方式,是打開瀏覽器的開發者工具,開啟 Network 面板,然後實際查看每一支 API 的呼叫,藉此快速定位是否是 API 對接的問題。假如發現 API 對接沒問題,就能快速回到程式碼查看其他部分,這時也可以透過埋 console
的方法,然後搭配開發者工具的 Console 面板,來查看不同的輸入與輸出結果。這種做法,會比上面的快速有效許多。
再來看看另一個例子,假如今天新功能在測試階段,產品端回報說頁面的加載異常的慢。如果在沒有額外工具的狀況下,只能盡可能地用上自己所知道的頁面效能優化的手段,但這種做法不是對症下藥,所以可能要試很多不同手段,才能有效優化。然而,如果有開發者工具,就可以開啟 Performance 面板,透過不同的方式,來快速定位加載慢是慢在哪。
希望透過上面兩個例子,讀者們有比較具體地感受到,當有了瀏覽器的開發者工具,前端工程師能更輕易地找出問題,這也是為什麼前端工程師需要懂如何善用開發者工具。
如何定位效能 (Performance) 相關問題?
首先,讓我們聚焦在 Performance 這個面板上,來談可以如何透過這個面板快速定位效能相關的問題。
查看瀏覽器生命週期事件
從使用者進到一個頁面之後,瀏覽器會也不同的生命週期事件,在 《請說明 DOMContentLoaded, load, beforeunload, unload 的觸發時機》 一文中,我們有介紹過這個面試中經常會考的問題。然而,比起去死記硬背這個面試題,用 Performance 面板中所展示的來理解會更有效。

假如打開 Perfomance 面板,然後點擊重新整理與錄製鍵,接著操作頁面,就可以出現類似上面這一張圖 (上面這張是拿 E+ 用的 Notion 頁面為例)。在圖中我們自己加了三個箭頭,分別是 DCL (DOMContentLoaded)、L (Load) 以及 LCP 的時間點。
可以看到,假如今天用 Performance 面板,就能很清楚地看到這些時間點,進而能夠去比較這些時間點是否有如預期發生。這能夠給前端工程師一個清楚的指引,來決定要不要花時間優化某些東西。
舉例來說,如果 DOMContentLoaded
太晚才發生,意味著瀏覽器花太多時間載入並解析 HTML 文件,如果要優化這塊,例如壓縮 HTML 檔案大小,移除不必要的註解和空白字符,或把阻塞 DOM 解析的 JavaScript 移到頁面底部,或用 defer
讓腳本在 DOM 解析完成後才執行 (在 《<script> 的 async 與 defer 有什麼不同?》 一文有詳談)。
查看每個函式所花費的時間
在看 Performance 面板時,我們也可以精細地去看每個函式所執行的時間。在這樣的一張火焰圖 (flame chart) 中,我們可以看到每一個函式呼叫所需的時間。

可以看到,在每一個函式被呼叫後,可能該函式底下又呼叫了其他函式,然後一層層呼叫下去。在這邊需要特別去區分兩個時間,一個是 total time 另一個是 self time (滑過會顯示),total time 是 self time 加上底下所有在被呼叫的函式所需的時間。
舉例來說,假如有個函式foo
呼叫 bar
,這時 foo
的 total time 是 foo
的 self time 加上 bar
的 self time。
在有了這個理解後,在看火焰圖時,就要專注在看 self time,太長的 self time 就會需要特別注意。之所以不看 total time,是因為即使一個函式的 total time 很長,也不代表是這個函式有問題。以上方截圖來講,該函式的整個 total time 是 722.47 毫秒,雖然在圖上面這個函式的呼叫看似很長,但其實不用擔心,因為該函式的 self time 只有 2.46 毫秒。
查看主執行緒有沒有被任務佔滿
最後想談一個在看 Performance 面板時,高頻率會看的,是主執行緒是否過度繁忙。在 JavaScript 中,除非使用 worker 來幫忙,不然基本上是單一執行緒。換句話說,如果主執行緒忙著處理任務,沒辦法妥善處理好下一輪的繪製,就會有所謂「掉幀」的狀況,而對使用者來說,就會覺得瀏覽器很卡很頓。
下圖是來自 Chrome 官方的《Analyze runtime performance》一文的範例,如果在 Performance 面板中有看到這種紅色的小塊狀在 Main 上面,就代表主執行緒被榨乾。

如《Measure performance with the RAIL mode》一文談到的,要讓人覺得畫面是順暢的,每秒需要渲染 60 幀 (也就是大家常看到的 60fps),換算起來每一幀最多只能有 16 毫秒 (1000 毫秒 / 每秒 60 幀),但因為瀏覽器會花約 6 毫秒處理繪製,所以真的能剩的是每幀 10 毫秒。
如果主行緒被榨乾,處理速度無法達到這個頻率,就會導致某些幀沒被繪製,就是上面提到的掉幀的卡頓狀況。要處理掉幀,透過 requestAnimationFrame
這類 Web API,能夠幫上大忙。
閱讀更多
在談完以上的基本內容後,接著我們會來談如何透過 Performance 面板查看 Web Vitals、requestAnimationFrame
實務上可以怎麼被用來解決效能問題,以及如何在 Network 面板上定位問題。這些內容都在 E+ 的主題文有近一步討論。
本文為 E+ 成長計畫的深度內容,截取段落開放免費閱讀。歡迎加入 E+ 成長計畫閱讀完整版本 (點此了解 E+ 的詳細介紹)。