如果前面是要注意的存储核心位置,那么这三个算是插件的重要的组成部分了。
了解熟悉上面这些东西是开发一个浏览器插件的基础。
当然这没有进行框架化的原生插件JS,使用浏览器插件框架之后这个一些代码注入流程可能还要更简便一些。
简单用人话讲:
同一个插件里的 三个“不同位置”的 JS 进程:
popup:小弹窗里的 JS
background:插件的大脑 / 后台服务
content script:被“注入网页里的间谍 JS”
特点来拆开讲 👇
popup(弹窗脚本)
对应:扩展图标点开后看到的那个小窗口里的 JS
出现位置:
点击浏览器工具栏右上角的扩展图标,弹出的那块 UI(HTML + CSS + JS)。
生命周期:
点开时创建,关掉就销毁。
每次打开都是“全新刷新”,之前的 JS 内存状态会没了。
能干嘛:
操作自己 popup 的 DOM(按钮、表单、列表这些)。
可以调用大部分 chrome.* API,如 chrome.storage、chrome.runtime.sendMessage 等。
不能干嘛:
不能直接操作网页 DOM(例如:不能直接 document.querySelector 去选当前 tab 的 DOM;那是 content script 的活)。
典型用途:
做一个小控制面板:设置项、开关、按钮;
显示当前 tab 的某些信息(通常要通过 background 或 content script 拿数据)。
background(后台脚本)
在 MV3 里多是 Service Worker 形式,是整个扩展的 大脑 + 中央调度。
运行位置:
不在任何网页里,也不在 popup UI 里,属于浏览器扩展自己的后台环境。
生命周期(MV3):
事件驱动:有事就唤醒(比如收到消息、浏览器事件触发),干完就挂起。
不再是一直常驻内存(MV2 里很多是 persistent background page)。
能干嘛:
监听浏览器事件:
安装、卸载、tab 更新、请求发送、右键菜单点击、快捷键等等。
统一管理数据和逻辑:
和多个 tab / 多个 content script / popup 通信;
负责权限较大的操作(如跨域请求、复杂逻辑、长时任务等)。
不能干嘛:
直接操作任何页面 DOM(跟 popup 一样,看不到网页里的元素)。
典型用途:
监听浏览器行为(比如请求、tab切换、右键菜单)。
做中心消息中转站:popup ⇄ background ⇄ content script。
做一些需要“比页面活得更久”的逻辑(在 MV3 里是事件驱动、但仍起这个主脑作用)。
简单示例:background.js (service worker)
// 监听来自 popup / content script 的消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'GET_TIME') {
sendResponse({ time: Date.now() });
}
});
content script(内容脚本)
这是真正跑在网页里的 JS,但又不是网页自己写的,是插件“注入”进去的。
运行位置:
嵌在某个网页中,共享同一个 DOM;
所以可以 document.querySelector、改页面样式、插入按钮等等。
生命周期:
随着页面加载而加载,随着页面关闭而结束;
每个 tab 上的每个匹配页面都可以有自己的一份 content script 实例。
能干嘛:
访问页面 DOM,改内容、添加 UI、监听点击等;
可以用 chrome.runtime.sendMessage 或 chrome.storage 与后台/其它部分交互。
不能干嘛:
不能直接用所有 chrome.* API(权限有限,像 tabs 有限制);
有“隔离世界”:不能随意直接访问网页里原生 JS 的变量,但可以通过注入 <script> 来桥接。
典型用途:
解析网页内容(比如抓取当前文章标题、选中文本等);
在网页上加按钮、浮动窗口、悬浮工具条;
做网页上的高亮、标注、自动填写等功能。
简单示例:contentScript.js
// 在网页右下角插一个按钮
const btn = document.createElement('button');
btn.textContent = '采集标题';
btn.style.position = 'fixed';
btn.style.right = '20px';
btn.style.bottom = '20px';
document.body.appendChild(btn);
btn.addEventListener('click', () => {
const title = document.title;
chrome.runtime.sendMessage({ type: 'SAVE_TITLE', title });
});
三者之间的关系(很重要)
可以这么类比一个插件的结构:
content script:
在每个网页里的“现场员工”——看得到 DOM,改得到页面。
popup:
给用户用的“小控制台”,用户点图标时看到的面板。
background:
后台老板 + 中央消息枢纽,负责协调各方、做高权限操作。
常见通信流:
用户在 popup 点了按钮 ➜ popup 发消息给 background ➜ background 再发消息给 content script,让它操作页面。
content script 采集到网页数据 ➜ 发送给 background ➜ background 存到 chrome.storage.local 或发网络请求 ➜ popup 打开时再向 background 要数据显示。
文章采用 知识共享署名 4.0 国际许可协议 进行许可,转载时请注明原文链接。