DevTools — 如何在開發者工具上 debug 原始程式碼?
2025年8月11日
在 如何用瀏覽器開發者工具 (DevTools) 定位效能相關問題? 一文中,我們談到可以如何透過瀏覽器的效能 (Performance) 分頁,來定位前端應用程式的效能問題。在這一期主題文中,我們會繼續探討開發者工具 (DevTools) 中的來源(Sources) 面板,讓 debug 變得更有效率、更快完成。
什麼是來源面板 (sources panel)?
相信多數讀者應該對瀏覽器的來源面板不陌生,在開啟瀏覽器的開發者工具後,點擊 Sources 分頁就能夠進到來源面板 (下方是瀏覽 E+ 的 Notion 內容站時,打開來源面板看到的內容)。
來源面板顧名思義,是讓開發者可以查看來源的地方。所謂的來源是指程式的原始碼 (source code),因此我們可以在來源面板中檢視各類構築起網站的檔案,包含 JavaScript 的檔案、跟樣式有關的 stylesheet,甚至是各類圖片的資源。
而現代的開發者工具,在來源面板中有提供一些非常有用的方法,能夠讓開發者用更高效的方式 debug。
如何在開發者工具上 debug 原始程式碼?
上一段落提到開發者可以在來源面板中,看到各類構築起網站的資源,然而在現代前端開發中,通常瀏覽器端拿到的程式碼,跟前端開發者最開始寫的程式碼,會看起來不太一樣。
這是因為現代前端框架通常會把程式碼做預處理,所以瀏覽器拿到的程式碼會是處理過後的版本。所以除非是寫純 HTML、CSS、JavaScript,不然前端工程師無法直接在開發者工具的來源面板上 debug。
前端程式碼的預處理有什麼好處與問題?
在往下談之前,相信如果對這塊還不熟的讀者,可能會問說「為什麼前端框架要先做預處理,不把前端工程師寫的原始版本直接給瀏覽器呢?」。
這是因為經過預處理的程式碼,檔案大小會比較小,所以瀏覽器在下載、解析上所需的時間也會比較短。
舉例來說,瀏覽器拿到以下這段程式碼
function a(b) {
const c = new Date().getFullYear();
return c - b;
}
上面的程式碼功能與下面這段原始程式碼是一模一樣的
function calculateUserAge(birthYear: number) {
const currentYear = new Date().getFullYear();
return currentYear - birthYear;
}
這段原始程式碼,在傳給瀏覽器之前,經過以下的預處理
- TypeScript 轉譯:因為瀏覽器無法直接處理 TypeScript,所以要先把 TypeScript 程式碼轉成 JavaScript
- Minified 最小化:原本的程式碼為了維持好的可讀性,在變數命名上會用
calculateUserAge
,但是對瀏覽器來說,用a
的效果也是一樣的,而比起原本的calculateUserAge
,只用a
所佔用的字元就比較少,也會讓下載與解析比較快
除了轉譯與最小化,前端框架通常也會順便處理打包 (bundling),讓程式碼可以不用一次載那麼多。在這些步驟都完成後,通常程式碼就會變得讓工程師難以閱讀的樣子 (更長一點的程式碼,最終可能轉換成下面這樣讓人無法輕易閱讀的版本)
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var
雖然說預先轉譯、最小化、打包能帶來好處,但顯然當程式碼到瀏覽器上變這樣,雖然瀏覽器能處理,但人類工程師要 debug 就會變得很困難。
如何 debug 被處理過,導致很難讀的程式碼?
上面談到預處理過的程式碼會很難 debug,那有沒有方法,可以在瀏覽器上也可以看到原始的程式碼呢?
Source map 在這時可以派上用場,根據 MDN 上的解釋 (連結),所謂的 source map 是一個把被處理過的程式碼,對應回原始程式碼的一張表。一般來說會是透過 JSON 的形式來表示。
以 MDN 上的例子來說,假如有個 SCSS 語法如下
ul {
list-style: none;
li {
display: inline;
}
}
這個 SCSS 語法會被轉換成以下的 CSS
ul {
list-style: none;
}
ul li {
display: inline;
}
/*# sourceMappingURL=index.css.map */
這中間的轉換就是透過 index.css.map
這個 source map
{
"version": 3,
"sourceRoot": "",
"sources": ["index.scss"],
"names": [],
"mappings": "AAAA;EACC;;AACA;EACC",
"file": "index.css"
}
上面的這張表,關鍵的點是 mappings
這串有被編碼過的字串,在瀏覽起收到後會解碼,然後就會拿到相關的資訊,讓瀏覽器知道如何對應處理過的程式碼。
具體來說,mappings
中的字串是透過 base64 VLQ 來編碼跟解碼;先前 Svelte 與 Rollup 的原創者 Rich Harris 有一個開源專案 vlq.js (連結),就有展示如何透過 vlq.js 來處理 source map (範例連結),推薦感興趣了解細節的讀者可以看看。
因此針對「在開發者工具的來源面板要如何 debug 原始程式碼」這個問題,只要透過 source map 就能做到。
閱讀更多
以上我們介紹了如何在開發者工具上 debug 原始程式碼?,關於使用瀏覽器的開發者工具,我們在 E+ 成長計畫中的主題文有更深入、實用的探討。
對更深入了解這個主題,以及其他前後端開發、軟體工程、AI 工程主題感興趣的讀者,歡迎加入 E+ 成長計畫一起成長 (連結)。