5月27日 22:36

如何开发 Chrome 浏览器插件?

Chrome 插件的核心架构是怎样的?

Chrome 插件由 Manifest、Background(Service Worker)、Content Script、Popup 四部分协作运行。Manifest 声明权限与入口,Service Worker 处理后台逻辑,Content Script 操作页面 DOM,Popup 提供交互界面。组件之间通过 chrome.runtime.sendMessagechrome.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 声明式规则更高效,但灵活性降低。

开发中有哪些常见坑?

  1. Service Worker 会休眠:MV3 的 Background 是 Service Worker,5 分钟无活动自动休眠,长连接用 chrome.alarms 保活
  2. Content Script 的 CSP 限制:不能使用内联脚本和 eval,所有逻辑必须放独立 JS 文件
  3. 消息回调丢失sendResponse 在异步场景下需返回 true 保持通道开放
  4. 权限最小化:只在 host_permissions 声明实际需要的域名,避免审核被拒
标签:Chrome