如何开发 Chrome 浏览器插件?
Chrome 插件的核心架构是怎样的?
Chrome 插件由 Manifest、Background(Service Worker)、Content Script、Popup 四部分协作运行。Manifest 声明权限与入口,Service Worker 处理后台逻辑,Content Script 操作页面 DOM,Popup 提供交互界面。组件之间通过 chrome.runtime.sendMessage 和 chrome.tabs.sendMessage 通信。
追问:Manifest V2 和 V3 有什么区别?MV3 用 Service Worker 替代了 Background Page,禁止远程代码执行,权限系统改为按需申请(optional_permissions),action 替换了 browser_action 和 page_action。
如何编写一个最小的 Chrome 插件?
只需要一个 manifest.json 和一个弹出页面:
json{ "manifest_version": 3, "name": "Hello Extension", "version": "1.0", "action": { "default_popup": "popup.html" } }
html<!-- popup.html --> <button id="btn">点击</button> <script src="popup.js"></script>
在 chrome://extensions 开启开发者模式,点击"加载已解压的扩展"即可运行。
追问:manifest_version 必须填 3 吗?Google 已强制要求新提交插件使用 MV3,旧 MV2 插件已无法上架 Chrome Web Store。
Content Script 和 Background 如何通信?
Content Script 注入到网页上下文,Background 运行在插件独立环境,两者不能直接访问对方变量,必须通过消息传递:
javascript// Content Script 发送 chrome.runtime.sendMessage({ type: "GET_DATA" }, (response) => { console.log(response.data); }); // Background 接收并回复 chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.type === "GET_DATA") { sendResponse({ data: "result" }); } });
反向通信用 chrome.tabs.sendMessage(tabId, payload)。
追问:如果需要跨域请求怎么办?在 Manifest 中声明 host_permissions,由 Background 发起 fetch,Content Script 通过消息获取结果。
常用 API 有哪些?
chrome.storage:持久化存储,分 local 和 sync 两种chrome.tabs:创建、查询、操作标签页chrome.webRequest/chrome.declarativeNetRequest:MV3 中后者替代前者处理请求拦截chrome.alarms:定时任务,Service Worker 休眠后仍可唤醒
追问:为什么 MV3 不推荐 chrome.webRequest?它以阻塞方式拦截请求,影响性能。declarativeNetRequest 声明式规则更高效,但灵活性降低。
开发中有哪些常见坑?
- Service Worker 会休眠:MV3 的 Background 是 Service Worker,5 分钟无活动自动休眠,长连接用
chrome.alarms保活 - Content Script 的 CSP 限制:不能使用内联脚本和
eval,所有逻辑必须放独立 JS 文件 - 消息回调丢失:
sendResponse在异步场景下需返回true保持通道开放 - 权限最小化:只在
host_permissions声明实际需要的域名,避免审核被拒