Chrome 浏览器插件(Extension)是前端开发者绕不开的一项重要技能。随着 Manifest V3 标准的全面推行,插件开发的范式也发生了巨大变化。本文将以 Service Worker 为核心,详述一个完整 Chrome 插件的开发全流程。

Chrome插件开发

一、Manifest V3 与 V2 的关键区别

Chrome 在 2024 年正式停止了对 Manifest V2 的支持,V3 架构带来了以下关键变化:

  • Background Page 变为 Service Worker:不再长期驻留内存,空闲时会被回收,需要事件唤醒
  • 网络请求改用 declarativeNetRequest:不再支持 webRequest API 的阻塞模式
  • Remotely Hosted Code 被禁止:所有 JavaScript 必须打包在插件内
  • Promises 全面支持:大部分 API 返回 Promise,告别回调地狱

二、创建 manifest.json

manifest.json 是插件的核心配置文件,声明了插件的身份、权限和入口点:

{ "manifest_version": 3, "name": "我的第一个插件", "version": "1.0.0", "description": "一个学习用的 Chrome 插件示例", "permissions": ["storage", "activeTab", "scripting"], "host_permissions": ["https://api.example.com/*"], "background": { "service_worker": "background.js" }, "action": { "default_popup": "popup.html", "default_icon": { "16": "icon16.png", "48": "icon48.png", "128": "icon128.png" } }, "content_scripts": [{ "matches": ["https://*.example.com/*"], "js": ["content.js"], "css": ["styles.css"] }] }
注意:host_permissions 必须显式声明跨域请求的目标域名,否则 Manifest V3 下所有跨域请求都会被拦截。permissions 中的 storage 用于访问 chrome.storage API。

三、Service Worker 的生命周期管理

V3 的 Service Worker 不再像 V2 那样持续运行,而是在被需要时激活,空闲约 30 秒后自动终止。这意味着全局变量无法可靠保存状态,必须使用 chrome.storage 持久化:

// background.js - Service Worker chrome.runtime.onInstalled.addListener(() => { chrome.storage.local.set({ installTime: Date.now() }); console.log('插件已安装'); }); // 监听消息 chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.type === 'get_data') { chrome.storage.local.get(['token'], ({ token }) => { fetch('https://api.example.com/data', { headers: { 'Authorization': `Bearer ${token}` } }) .then(res => res.json()) .then(data => sendResponse({ ok: true, data })) .catch(err => sendResponse({ ok: false, error: err.message })); }); return true; // 必须返回 true 表示异步响应 } });

四、Content Script 与页面通信

Content Script 运行在目标网页的上下文中,可以访问 DOM 但不能直接使用 chrome.* API 的大部分功能。与 Service Worker 的通信通过消息传递完成:

Content Script通信
// content.js // 从页面中提取数据 const text = document.querySelector('h1')?.innerText; // 发送给 Service Worker chrome.runtime.sendMessage( { type: 'page_data', text, url: location.href }, (response) => { console.log('Service Worker 回复:', response); } ); // 监听来自 Service Worker 的消息 chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.type === 'highlight') { document.body.style.backgroundColor = '#fef9e7'; sendResponse({ ok: true }); } });

五、Popup 弹窗开发

Popup 是用户点击工具栏图标时弹出的小窗口,本质是一个独立的 HTML 页面:

<!-- popup.html --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> body{width:320px;padding:16px;font-family:sans-serif} h2{font-size:16px;color:#333;margin-bottom:12px} button{width:100%;padding:10px;background:#1976d2;color:#fff; border:none;border-radius:6px;cursor:pointer} button:hover{background:#1565c0} .status{margin-top:10px;font-size:13px;color:#666} </style> </head> <body> <h2>数据分析助手</h2> <button id="analyze">分析当前页面</button> <div class="status" id="status"></div> <script src="popup.js"></script> </body> </html>
// popup.js document.getElementById('analyze').addEventListener('click', async () => { const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); const response = await chrome.tabs.sendMessage(tab.id, { type: 'analyze' }); document.getElementById('status').textContent = '分析完成:' + JSON.stringify(response); });

六、Options 设置页面

Options 页面可以为用户提供配置入口,如 API 地址、偏好设置等。在 manifest.json 中声明后,右键插件图标即可看到"选项"入口:

// manifest.json 中添加 "options_ui": { "page": "options.html", "open_in_tab": true }

七、打包与发布

开发完成后,需要将插件打包为 .crx 或 .zip 文件:

  • 本地测试:打开 chrome://extensions/ → 开启"开发者模式" → 加载已解压的扩展程序
  • 生产打包:使用 npm run build(如 Webpack)压缩代码后,将产物放入 dist 目录
  • Chrome Web Store:需注册开发者账号(一次性费用 5 美元),上传 .zip 包并填写描述后提交审核

总结

Chrome 插件开发虽然入门门槛不高,但要写出一个高质量、稳定运行的插件,需要对 Manifest V3 规范有深入理解。本文涵盖了从配置文件到消息通信的全流程,希望能为有志于插件开发的读者提供一个系统的参考框架。在实际项目中,建议多加测试尤其是 Service Worker 的唤醒逻辑,这是 V3 架构中最容易出现隐蔽 Bug 的地方。