各组件调试
本教程共 56 篇 · 第 47 篇 · 更新于 2026-08-13 · 约 7 分钟阅读
本节目标:学完你能分别打开 popup、options、服务工作者、内容脚本这四类组件的调试面板,知道每个组件的日志会打在哪个控制台,不再满世界找自己的
console.log。
上一章我们把扩展装进了浏览器。但扩展调试真正让新手崩溃的地方在于:它不是一个页面,而是好几个互相独立的运行环境。你在内容脚本里打的日志,不会出现在后台控制台;你在 popup 里打的日志,也不在网页控制台。找错地方,就会误以为”代码没执行”。
这一节我们把每个组件的调试入口挨个走一遍。
47-1 先搞清楚有几个独立上下文
MV3 扩展在运行时通常同时存在这几个上下文,各自有一套独立的 console:
- 服务工作者:后台脚本,没有界面,日志在专属的检查视图里。
- popup 弹出页:点工具栏图标弹出的小窗,是一个独立页面。
- options 选项页:设置页面,也是一个独立页面。
- 内容脚本:注入到网页里,和宿主页面共享同一个控制台。
理解这一点,调试就一半通了:先问”这段代码跑在哪个上下文”,再去对应的控制台看日志。
Note这些上下文之间不共享变量,也不共享控制台。所以”日志找不到”绝大多数时候不是代码没跑,而是你打开了错误的面板。
47-2 调试 popup 弹出页
popup 是最容易调试出问题的组件,因为它太”闪”了——鼠标一点别的地方,它就关了,控制台也跟着消失。正确做法是给它单独开一个 DevTools。
步骤是:先点工具栏图标把 popup 打开,然后在 popup 上右键,选”检查”。这会弹出一个独立的 DevTools 窗口,专门对着这个 popup。这个窗口打开期间,popup 不会因为失焦而关闭,你可以放心地看日志、改样式、打断点。
给 popup 加日志和普通网页一样,注意脚本要外链,不能写内联脚本:
<html>
<body>
<h1>Hello Extensions</h1>
<script src="popup.js"></script>
</body>
</html>
console.log('这是 popup 的日志');
打开 DevTools 后,这行日志就会出现在它的 Console 里。如果 popup.js 有语法错误,同一个控制台会显示红色报错,直接告诉你哪行出了问题。
Tippopup 改完 HTML/CSS/JS 不用重新加载扩展,关掉再点一次图标就是最新的。这点和后台脚本不一样,别白点重新加载。
47-3 调试 options 选项页
options 页本质就是一个扩展内部的普通网页,所以调试方式最省事:把它当网页对待。
打开方式有两种。一是在 chrome://extensions 的扩展卡片里点”详情”,找到”扩展程序选项”进入;二是在页面上直接右键选”检查”,或者按 F12 打开 DevTools。两种方式打开的都是完整的 DevTools,Console、Sources、Elements 全都能用。
因为它是独立标签页或独立窗口,不存在 popup 那种”一失焦就关”的问题,调试体验最舒服。想验证设置有没有存进去,在它的控制台里直接调 API 就行:
// 在 options 页控制台执行,查看已保存的设置
await chrome.storage.sync.get(null);
和 popup 一样,options 页改完也不需要重新加载扩展,刷新页面即可。
47-4 调试服务工作者
后台没有界面,所以入口在扩展管理页里。到 chrome://extensions 找到你的扩展卡片,点上面的 “Service Worker”(有的版本显示为”检查视图:Service Worker”)链接,就会弹出后台的专属 DevTools。
这个面板和网页 DevTools 一样好用:Console 看日志、Sources 打断点、Network 看后台发的请求。
chrome.runtime.onInstalled.addListener(() => {
console.log('后台已启动');
});
有两个特点必须注意。第一,服务工作者是事件驱动、可能随时休眠的,面板打开后没日志很正常,去触发一次对应事件(点图标、发消息)把它唤醒即可。第二,后台脚本改完必须在卡片上点”重新加载”,新代码才会生效。
更细的后台调试技巧(报错含义、断点注意事项)我们在第 15 章已经专门讲过,这里只作为组件之一收进速查表。
47-5 调试内容脚本
内容脚本的日志不在后台面板,也不在 popup 面板,而是在它注入的那个网页的控制台里。
所以调试流程是:打开被注入的目标网页,按 F12 打开该网页的 DevTools,切到 Console,就能看到内容脚本的输出和报错。
console.log('内容脚本已注入', location.href);
这里有个坑:网页控制台默认执行环境是页面本身,而内容脚本跑在隔离环境(isolated world)里。所以你在控制台直接敲 chrome.runtime.sendMessage(...),可能会提示 chrome 未定义或权限不足。解决办法见下一小节。
想确认脚本到底注入没注入,Sources 面板里有一栏专门列出内容脚本(通常叫 Content scripts),能看到它的源码,也能在上面打断点。列表里没有你的文件,说明 matches 没匹配上,回去检查匹配规则。
Tip内容脚本改完要”两步走”:先在扩展卡片上点重新加载,再刷新宿主网页。只做一步,跑的还是旧脚本。
47-6 在控制台切换执行上下文
网页 DevTools 的 Console 面板顶部有一个下拉框(通常显示 top),它用来选择”我这行命令在哪个环境里执行”。
点开这个下拉框,你会看到页面本身,以及你的扩展名对应的一项。选中扩展那一项,控制台就切到内容脚本的隔离环境里,这时候敲 chrome.runtime.getURL('/') 之类的扩展 API 才能正常返回。
// 切到扩展上下文后再执行,才拿得到扩展 API
chrome.runtime.getURL('/');
这个下拉框是内容脚本调试的关键开关,很多人不知道它的存在,白白折腾半天。记住:看日志不用切,敲扩展 API 必须切。
47-7 调试入口速查表
把四类组件汇总成一张表,忘了就回来查:
| 组件 | 调试入口 | 日志出现在 | 改完是否需重新加载扩展 |
|---|---|---|---|
| popup 弹出页 | 打开 popup 后右键”检查” | popup 专属 DevTools | 不需要 |
| options 选项页 | 打开该页后 F12 或右键”检查” | 该页 DevTools | 不需要 |
| 服务工作者 | 扩展卡片上点 “Service Worker” | 后台专属 DevTools | 需要 |
| 内容脚本 | 宿主网页按 F12 | 宿主网页控制台 | 需要(并刷新网页) |
47-8 调试心法
最后总结成三句话,能省掉你大量困惑:
- 先定位上下文,再找控制台。 日志”消失”几乎都是面板开错了。
- 区分刷新规则。 后台和内容脚本改完要重新加载,页面类组件关开即可。
- 善用控制台直查。 与其反复加日志重跑,不如在对应控制台里直接
await chrome.storage.local.get(null),一行验证数据到底存没存。
调试的本质,就是把看不见的运行过程变成看得见的信息。四个入口记牢,扩展对你来说就不再是黑盒了。