服务工作者基础
本教程共 56 篇 · 第 12 篇 · 更新于 2026-08-13 · 约 6 分钟阅读
本节目标:学完你能说清楚服务工作者和”一直常驻的后台”到底差在哪,知道它为什么会被随时停止,并能在清单里正确声明一个后台脚本。
在 Manifest V3 里,扩展的”后台”不再是常驻内存的页面,而是一个服务工作者(Service Worker)。你不用再去想”常驻后台页面”那套思路,因为从根子上就变了:这个后台平时是休眠的,只有事件发生时才会被浏览器唤醒,干完活再睡回去。理解这一点,后面所有后台代码才不会写跑偏。
很多新手第一次接触服务工作者会困惑:为什么我存到变量里的数据下次就没了?为什么定时器到点没响?原因就是没搞懂它的”非持久”本质。这一节先把地基打牢。
12-1 什么是服务工作者
服务工作者是一个特殊的 JavaScript 脚本,运行在浏览器自己的进程里,不在任何网页里,也不在弹出页里。它负责在”没有界面”的时候替扩展处理事情:比如监听扩展被安装、定时拉取数据、在不同组件之间转发消息。
它最大的特点就一句话——事件驱动、非持久。平时它不占资源,处于停止状态;当某个事件被触发(例如用户点了工具栏图标、有消息发来、闹钟时间到了),浏览器才把它启动起来执行对应的监听函数;函数执行完、没有后续任务了,它又会被停止。
这正是 Manifest V3 相对旧架构的核心变化:后台从”一直开着”变成了”按需唤醒”。对浏览器来说更省电、更省内存;对你来说,写代码的方式也要跟着变。
Note服务工作者运行在扩展自己的上下文里,不是页面上下文。它拿不到
window、document这些网页才有的东西,也访问不了某个具体网页的 DOM。要操作页面,得通过消息通信让内容脚本去干。
12-2 与常驻后台的本质区别
如果你之前听说过”扩展后台会一直活着”,那是另一套架构的印象。在 V3 里要彻底换脑子:
- 常驻模型:脚本启动后一直挂在内存里,变量常驻、定时器常跑、随时能响应。代价是占用资源,浏览器难回收。
- 服务工作者模型:脚本平时停止,被事件唤醒才运行,跑完即停。变量不会一直留着,定时器不能用来做长周期保活。
这里的关键不是”能不能常驻”,而是”设计上就不该依赖常驻”。很多旧习惯(比如把登录态塞进一个全局变量、靠 setInterval 每几秒轮询)在新模型下会出问题,因为服务工作者睡着以后那些变量和定时器都没了。
Tip判断一段后台逻辑对不对,先问一句:如果这段代码五分钟前被停止、现在才被事件唤醒,它还能正常工作吗?能,就写对了。
12-3 在清单里注册服务工作者
声明方式非常直接:在 manifest.json 里加一个 background 字段,用 service_worker 指向你的脚本文件。
{
"manifest_version": 3,
"name": "我的扩展",
"version": "1.0",
"background": {
"service_worker": "background.js"
}
}
就这么一行 service_worker,浏览器就知道:“这个扩展的后台脚本是 background.js,请按服务工作者规则来管理它。” 注意 background 字段在 V3 里只能指向单个 JS 文件(不能是 HTML 页面),可选加 type: "module" 启用 ES 模块(见下节)。
12-4 用 ES 模块组织后台代码
如果后台逻辑变多,你可以用 ES 模块拆分,主脚本里 import 其他文件。只要在清单里把 type 设为 "module":
{
"background": {
"service_worker": "background.js",
"type": "module"
}
}
然后主脚本里就能正常 import:
import './sw-omnibox.js';
import './sw-tips.js';
console.log('服务工作者已注册');
// sw-omnibox.js
console.log('omnibox 模块已加载');
用模块拆分有个好处:不同功能各管各的文件,调试时一眼能看出哪块注册了、哪块没加载。但要注意,无论拆成多少个模块,它们最终都跑在同一个服务工作者实例里,遵循同一套”唤醒—停止”规则。
12-5 服务工作者的生命周期
理解生命周期,是写对后台代码的前提。它大致分三步:
- 注册与启动:扩展加载(或你点 reload)时,浏览器读取清单,注册服务工作者。此时它不一定立即运行,只是完成注册。
- 被事件唤醒:当某个已注册的事件触发(例如
runtime.onInstalled、闹钟、onMessage),浏览器启动服务工作者,执行对应的监听函数。 - 闲置后停止:所有事件处理完成、没有正在进行的异步任务后,浏览器会在一段时间后把它停止,释放资源。
这里有个容易踩的坑:唤醒是”事件触发”才发生的。如果你的代码逻辑依赖”后台一直在线等待”,那它永远不会被触发。正确做法是把所有要响应的动作,都挂在事件监听器上,而不是写在顶层等它自己跑。
Tip想在开发时确认服务工作者有没有被唤醒、有没有被停止,去
chrome://extensions打开对应扩展的”检查视图”(服务工作者调试面板)就能看到。下一节和本章 15 会专门讲调试。
12-6 服务工作者能用到什么
服务工作者里能用的是 chrome.* 扩展 API 和标准的 Web 平台能力(fetch、WebSocket、Promise 等),但有几类东西它没有:
- 没有
window、document,不能操作 DOM。 - 没有网页那种
localStorage,要存数据请用chrome.storage。 - 没有持续运行的全局定时器来”保活”,长周期任务请用
chrome.alarms。
这些限制不是 bug,而是设计。它们逼着扩展走”事件驱动 + 持久化存储”的路线,这也是 MV3 后台稳定、省资源的根本原因。下一章我们就专门讲:到底该注册哪些事件、怎么写才对。