Chrome DevTools中的現(xiàn)代Web調(diào)試
大家好,我是 CUGGZ。
如今,開(kāi)發(fā)者通常會(huì)利用框架、構(gòu)建工具和編譯器從更高級(jí)別的角度來(lái)編寫 Web 應(yīng)用程序。在 DevTools 中調(diào)試或分析 Web 應(yīng)用程序時(shí),目前能查看和調(diào)試的都是已經(jīng)編譯的代碼,而不是實(shí)際編寫的代碼。很多時(shí)候,我們并不想調(diào)試已經(jīng)編譯、壓縮后的代碼,而是想調(diào)試原始代碼:
使用 TypeScript 時(shí),不想調(diào)試編譯之后的 JavaScript,而是想調(diào)試原始的 TypeScript 代碼;
當(dāng)使用 Angular、JSX 之類的模板時(shí),并不希望調(diào)試生成的 DOM。而是調(diào)試自己編寫的組件。
總而言之,我們可能希望在編寫自己的代碼時(shí)對(duì)其進(jìn)行調(diào)試。雖然 source maps 已經(jīng)在一定程度上縮小了這一差距,但 Chrome DevTools 和生態(tài)系統(tǒng)可以在這方面做更多的事情。下面就來(lái)看一看吧!
1. Deployed 和 Authored 代碼
目前,在 Sources 面板中導(dǎo)航文件樹(shù)時(shí),可以看到已編譯(通常已壓縮)包的內(nèi)容,這些是瀏覽器下載和運(yùn)行的實(shí)際文件。DevTools 將其稱為 Deployed 代碼。
這在調(diào)試時(shí)可能并不是很方便,我們希望查看和調(diào)試自己編寫的代碼,而不是打包完的代碼。為了彌補(bǔ)這一點(diǎn),現(xiàn)在可以通過(guò)樹(shù)來(lái)顯示我們編寫代碼(這被稱為 Authored 代碼)。這使得樹(shù)更接近于在 IDE 中看到的源文件,并且這些文件現(xiàn)在與 Deployed 代碼是分離的:
可以在 Chrome DevTools 中開(kāi)啟此選項(xiàng):DevTools > Settings > Experiments > Group sources into Authored and Deployed trees.
注:Chrome DevTools 團(tuán)隊(duì)計(jì)劃很快默認(rèn)啟用此實(shí)驗(yàn)選項(xiàng)。
2. Just my code
注:這是 Chrome Canary 106 版本的預(yù)覽功能。?
當(dāng)使用依賴項(xiàng)或在框架之上構(gòu)建應(yīng)用時(shí),第三方文件可能會(huì)阻礙我們的調(diào)試。多數(shù)時(shí)候,我們只想調(diào)試自己編寫的代碼,而不是隱藏在 node_modules 文件中的某些第三方庫(kù)的代碼。
為了彌補(bǔ)這一點(diǎn),DevTools 默認(rèn)啟用了一個(gè)額外的設(shè)置:自動(dòng)將已知的第三方腳本添加到忽略列表??梢栽?nbsp;DevTools > Settings > Ignore List 中找到它。
啟用此設(shè)置后,DevTools 會(huì)隱藏框架或構(gòu)建工具標(biāo)記為忽略的任何文件或文件夾。作為開(kāi)發(fā)者,我們不需要做任何事情來(lái)啟用這種新的行為,具體實(shí)施取決于框架。比如,從 Angular v14.1.0 開(kāi)始,其 node_modules 和 webpack 文件的內(nèi)容已被標(biāo)記為忽略。因此,這些文件夾、其中的文件等都不會(huì)出現(xiàn)在 DevTools 的各個(gè)位置。
(1)在堆棧跟蹤中
這些被忽略的文件不再出現(xiàn)在堆棧跟蹤中,現(xiàn)在可以看到更多相關(guān)的堆棧跟蹤信息:
如果想查看堆棧跟蹤的所有調(diào)用幀,可以單擊顯示更多幀鏈接。
這同樣適用于在調(diào)試和單步執(zhí)行代碼時(shí)看到的調(diào)用堆棧。當(dāng)框架或打包程序通知 DevTools 的第三方腳本時(shí),DevTools 會(huì)自動(dòng)隱藏所有不相關(guān)的調(diào)用框架并在單步調(diào)試時(shí)跳過(guò)任何被忽略的代碼。
(2)在文件樹(shù)中
要想在 Sources 面板的 Authored 代碼樹(shù)中隱藏忽略的文件和文件夾,需要在 DevTools 的 Settings > Experiments 中選中 Hide ignore-listed code in sources tree view。
在示例的 Angular 項(xiàng)目中,node_modules 和 webpack 文件夾現(xiàn)在已經(jīng)隱藏了:
(3)在快速打開(kāi)菜單中
被忽略的代碼不僅可以在文件樹(shù)中隱藏,還可以在“快速打開(kāi)”菜單(快捷鍵:Control+P (Linux/Windows) 或 Command+P (Mac))中隱藏。
3. 對(duì)堆棧跟蹤的改進(jìn)
Chrome DevTools 對(duì)堆棧跟蹤引入了更多改進(jìn)。
(1)Linked 堆棧跟蹤
當(dāng)某些操作是異步觸發(fā)時(shí),DevTools 中的堆棧跟蹤目前只能顯示部分情況。例如,在 framework.js? 文件中有一個(gè)簡(jiǎn)單的 scheduler:
function makeScheduler() {
const tasks = [];
return {
schedule(f) {
tasks.push({ f });
},
work() {
while (tasks.length) {
const { f } = tasks.shift();
f();
}
},
};
}
const scheduler = makeScheduler();
function loop() {
scheduler.work();
requestAnimationFrame(loop);
};
loop();
在 example.js? 文件中使用 scheduler:
function someTask() {
console.trace("done!");
}
function businessLogic() {
scheduler.schedule(someTask);
}
businessLogic();
在 someTask? 方法中添加斷點(diǎn)或檢查控制臺(tái)中打印的跟蹤時(shí),看不到任何與 businessLogic() 調(diào)用相關(guān)的信息:
在堆棧跟蹤中也看不到面包屑來(lái)幫助我們找出導(dǎo)致該任務(wù)的事件之間的因果關(guān)系。多虧了一個(gè)名為“Async Stack Tagging”的新功能,通過(guò)將異步代碼的兩個(gè)部分鏈接在一起,解決了這個(gè)問(wèn)題。
Async Stack Tagging API 引入了一個(gè)名為 console.createTask() 的新控制臺(tái)方法。API 簽名如下:
interface Console {
createTask(name: string): Task;
}
interface Task {
run<T>(f: () => T): T;
}
console.createTask()? 調(diào)用返回一個(gè) Task 實(shí)例,可以使用它來(lái)運(yùn)行任務(wù)的內(nèi)容 f。
// 任務(wù)創(chuàng)建
const task = console.createTask(name);
// 任務(wù)執(zhí)行
task.run(f);
該任務(wù)形成了創(chuàng)建它的上下文和正在執(zhí)行的異步函數(shù)的上下文之間的鏈接。
注:Async stack tagging API 將在 Chrome 106 中可用。
把它應(yīng)用到 makeScheduler 函數(shù)中,代碼變?yōu)榱诉@樣:
function makeScheduler() {
const tasks = [];
return {
schedule(f) {
const task = console.createTask(f.name);
tasks.push({ task, f });
},
work() {
while (tasks.length) {
const { task, f } = tasks.shift();
task.run(f); // instead of f();
}
},
};
}
有了它,Chrome DevTools 現(xiàn)在能夠更好的顯示堆棧跟蹤:
注意,businessLogic()? 現(xiàn)在是如何包含在堆棧跟蹤中的。不僅如此,該任務(wù)的名稱為 someTask? 而不是像以前那樣通用的 requestAnimationFrame。
(2)友好的調(diào)用幀
在構(gòu)建項(xiàng)目時(shí),框架通常會(huì)從各種模板語(yǔ)言生成代碼,例如 Angular 或 JSX 模板,它們將看起來(lái)像 HTML 的代碼轉(zhuǎn)換為最終在瀏覽器中運(yùn)行的純 JavaScript。有時(shí),這些生成的函數(shù)被命名為不太友好的名稱——要么是壓縮后的單字母名稱,要么是一些晦澀或不熟悉的名稱。
在示例項(xiàng)目中,包含一個(gè)名稱:AppComponent_Template_app_button_handleClick_1_listener,可以在堆棧跟蹤中看到它:
為了解決這個(gè)問(wèn)題,Chrome DevTools 現(xiàn)在支持通過(guò) source maps 重命名這些函數(shù)。作為開(kāi)發(fā)者,我們無(wú)需執(zhí)行任何操作即可啟用此功能,具體實(shí)施取決于框架。
通過(guò)本文列出來(lái)的新增功能,Chrome DevTools 可以為我們提供更好的調(diào)試體驗(yàn)!Chrome 團(tuán)隊(duì)還想探索更多領(lǐng)域,特別是如何改善 DevTools 中的分析體驗(yàn)。期待 Chrome DevTools 未來(lái)可以帶來(lái)更友好的調(diào)試體驗(yàn)!
參考:https://developer.chrome.com/en/blog/devtools-modern-web-debugging/