Chrome 插件开发
从一个真实问题开始
我经常在浏览器里看技术文章。看到好的想存到 Obsidian,复制粘贴格式全乱。打开"另存为"保存下来是带广告、导航栏、侧边栏的 HTML。想找一个干净的 Markdown 版本,要么没有,要么是闭源插件不敢用。
于是我开始想:我能不能自己写一个?
这是个典型的"想动手"时刻。但真正动手之前,有几个更前置的问题需要想清楚:
- Chrome 插件到底是什么?和 userscript、网页工具、PWA 差在哪?
- 我想做的这个事,到底该用哪种形态?
- 学 Chrome 插件的"投资回报"如何?是一次性投入还是持续折腾?
写这篇文章的目的,是在你打开 manifest.json 之前,帮你想清楚这三个问题。
插件是什么
先把"插件"这个词拆开看。
Chrome 插件(Chrome Extension),也叫浏览器扩展,本质上是一段运行在 Chrome 浏览器里的代码。它能访问一些普通网页拿不到的 API,比如读取当前标签页的 URL、修改请求头、在用户点击工具栏图标时弹出一个小页面。
可以把它理解为:
插件 = 对浏览器的扩展能力 + 对已有网站的增强能力
注意两个关键词:“对浏览器” 和 “对已有网站”。这两个词决定了插件能做什么、不能做什么。
对浏览器意味着插件能拿到浏览器层面的能力,比如:
- 操作标签页(关闭、新建、切换)
- 读取和修改浏览器历史
- 拦截和修改网络请求
- 在工具栏添加图标
- 监听键盘快捷键
对已有网站意味着插件的核心战场是"改造现有网站",比如:
- 给维基百科加一个深色模式
- 给 GitHub 加一个一键复制文件链接的按钮
- 给掘金、知乎、CSDN 屏蔽某些干扰元素
插件能做什么、不能做什么
能做的:
- 改造已有网站(修改 DOM、注入脚本)
- 提供一个常驻工具栏入口(点击图标触发动作)
- 跨页面保存数据(用户的偏好、笔记、历史)
- 监听浏览器事件(标签页变化、下载事件)
不能做(或做起来很费劲):
- 完全独立的产品(需要服务端配合的复杂功能)
- 移动端体验(Chrome 插件不适用于移动浏览器)
- 高性能要求的事(不适合跑复杂的计算任务)
- 跨浏览器一致体验(Firefox、Edge、Safari 各有差异)
什么时候该用插件
给几个真实场景,帮你判断。
适合用插件的场景:
- 改造已有网站:给某个你不喜欢的网站加功能或去干扰
- 跨页面工具:复制当前页面内容、抓取数据、自动填表
- 浏览器层的小工具:标签页管理、下载管理、截图、翻译
- 给开发者自己用:调试、API 测试、页面抓取
不适合用插件的场景:
- 需要登录、要用户数据、要后端服务:你应该做个完整的 Web 应用
- 需要跨设备同步、要复杂的用户系统:插件不是产品形态的完整答案
- 想要完整的移动端体验:Chrome 插件在手机上几乎用不上
- 想做一个完整的 SaaS 产品:插件只是入口,不是产品
一个简单的判断标准:
如果你的核心场景是"我在浏览某个网站时想多做点什么",用插件。
如果你的核心场景是"用户打开我的产品完成某件事",用 Web 应用。
插件和其他形态的对比
把插件和几种常见的形态放一起看。
| 形态 | 优点 | 缺点 | 适合什么 |
|---|---|---|---|
| Chrome 插件 | 触发快、分发简单、有浏览器 API | 平台限制 Chrome 生态、需要上架审核 | 改造已有网站、浏览器层小工具 |
| Userscript(油猴脚本) | 写起来简单、不用上架 | 分发依赖 Greasy Fork、不能调浏览器 API | 纯改页面的轻量需求 |
| 网页小工具 | 跨平台、跨浏览器 | 每次要打开新页面、不能主动操作当前页面 | 数据展示、计算、查询 |
| PWA | 能离线、能装到桌面 | 浏览器 API 能力受限、用户认知度低 | 阅读类、内容类工具 |
| 桌面应用(Electron 等) | 能力强、跨平台 | 包大、分发麻烦、用户安装成本高 | 复杂客户端、离线优先 |
| 书签(Bookmarklet) | 一行 JS 就能写、零分发成本 | 能力极弱、不能存数据 | 极简工具 |
一个具体例子:把当前页面存成 Markdown
- 插件:点工具栏图标,触发下载,几秒钟搞定。✅ 适合
- Userscript:能改页面但分发靠 Greasy Fork,朋友想用要去搜。⚠️ 凑合
- 网页工具:复制 URL 粘贴到新页面处理。❌ 太麻烦
- 桌面应用:包太大。❌ 杀鸡用牛刀
- 书签:完全做不了。❌ 能力不够
一个反例:做个团队协作笔记
- 插件:能做入口,但需要后端、需要用户系统、需要数据同步。⚠️ 勉强
- Web 应用:自然形态,用户打开就能用。✅ 适合
记住这个判断方法:
先看"我做的事情发生在哪个上下文里"。
发生在浏览网页时 → 插件 / userscript。
发生在打开我的产品时 → Web 应用。
需要长期运行、复杂计算 → 桌面应用。
一个插件的最小构成
一个 Chrome 插件由几个独立的"部分"组成。每个部分在不同的上下文里运行,之间通过消息通信协作。
1┌─────────────────────────────────────────┐
2│ 工具栏图标 │
3│ 点击 → 弹出 popup.html │
4└──────────────┬──────────────────────────┘
5 │ sendMessage
6 ↓
7┌─────────────────────────────────────────┐
8│ content script │
9│ 注入到目标网页,能读/改页面 DOM │
10└──────────────┬──────────────────────────┘
11 │ 异步通信
12 ↓
13┌─────────────────────────────────────────┐
14│ background (service worker) │
15│ 后台运行,处理跨页面的逻辑 │
16│ 存数据、调浏览器 API │
17└─────────────────────────────────────────┘
manifest.json:插件的身份证
每个插件必须有一个 manifest.json 文件。这是插件的元信息,Chrome 靠它认识你的插件:叫什么、用什么权限、能做什么。
content script:注入到目标页面
content script 是注入到目标网页里的 JavaScript。它能读取和修改页面的 DOM,但运行在一个"隔离的世界"里,不能访问页面的 JavaScript 变量。
这是插件最核心的能力:你能用代码改造任何网站。
popup:点击图标弹出的页面
popup 是用户点击工具栏图标时弹出的一个 HTML 页面。本质上就是一个普通网页,只是尺寸小、生命周期短。
background (service worker):后台常驻逻辑
V3 时代,background 不再是常驻页面,而是一个 service worker。它在需要时被唤起,处理完逻辑后会休眠。
不要把大量状态存在 service worker 里。它不是常驻进程。
options page:用户配置(可选)
如果你的插件有用户偏好,可以加一个 options 页面。用户在 chrome://extensions 里点"选项"进入。
icons:图标
插件必须有图标。商店要求至少 16/32/48/128 像素各一张。哪怕是占位图也要有。
这几部分怎么协作?
一个典型的数据流:
- 用户点击工具栏图标 → 弹出 popup
- popup 按钮触发 → 给 content script 发消息
- content script 提取页面内容 → 传给 popup
- popup 把内容通过 downloads API 触发下载
- 用户偏好(如选择器、文件名格式)存到 chrome.storage
这三层(popup / content script / background)之间的通信是插件开发的核心难点。比 API 本身重要得多。
Manifest V3 必须知道的几件事
如果你看过一些老教程,会发现很多代码是跑不通的。原因是 Chrome 在 2020 年宣布了 Manifest V3,V2 已经在 2024 年完全停用。
V3 的几个关键变化:
1. background 变成 service worker
V2 时代 background 是一个常驻页面(persistent: true)。V3 改成 service worker,逻辑执行完就休眠,不能依赖它常驻。
这意味着:
- 不能在 background 里存全局变量
- 不能依赖 background 一直运行
- 需要长连接、长时间任务要换思路
2. 拦截请求用 declarativeNetRequest,不用 webRequest
V2 时代可以用 webRequest API 拦截和修改请求。V3 把这个能力收紧了,只能用 declarativeNetRequest。
差别:
webRequest:能读请求、能改请求、能阻塞declarativeNetRequest:只能基于规则匹配和重定向,不能动态改请求体
对你的影响:
- 如果你的插件只改页面 DOM,不拦截请求,这两种 API 跟你无关
- 如果你的插件要做广告拦截、请求改写,要按 V3 规则重写
3. host_permissions 显式声明
V2 时代权限写在 permissions 里就行。V3 把"哪些网站能访问"拆出来放在 host_permissions。
1{
2 "permissions": ["storage", "downloads"],
3 "host_permissions": ["https://*.example.com/*"]
4}
4. 远程代码执行被禁止
V2 时代可以从 CDN 加载脚本。V3 不允许,所有代码必须打包进插件里。
要不要学 V2?
不用。
- V2 已停用,新插件审核不通过
- 老教程里 V2 的 API 命名、概念在 V3 里都有对应,但写法不同
- 直接学 V3 就行,不要走弯路
上架一个插件的成本和周期
写完插件只是第一步。要让别人也能用,需要发到 Chrome Web Store。
成本
5 美元一次性注册费。需要 Visa 卡,注册过程需要科学上网(Google 服务在国内的访问问题)。
时间
材料准备大概 1-2 小时:
- 插件代码(zip 打包)
- 4 个尺寸的图标(16/32/48/128)
- 商店图标(128x128,必须)
- 商店截图(1280x800 或 640x400,至少 1 张)
- 简短描述(最多 132 字符)
- 详细描述
- 隐私声明 URL(哪怕只是个 GitHub Pages 页面)
审核周期
首次提交 1-3 天。被打回再提交通常 1 天内。
最常见的打回原因:
- 缺少 privacy policy URL
- 权限申请超出实际需要
- 插件描述不清楚 single purpose(一个插件做太多事)
- icon 用了 Google 商标或禁用素材
如果只是给自己用:
不用上架。打开 chrome://extensions,开开发者模式,“加载已解压的扩展程序"选你的文件夹就行。代码改完点插件详情页的刷新按钮。
下一步
如果你看完还是想做 Chrome 插件,先回答两个问题:
- 你的核心场景发生在浏览网页时吗? 如果是,继续。
- 你的核心场景需要后端服务吗? 如果不需要,插件是合适形态。
满足这两个条件,就值得动手。
关于"具体怎么做”,看 《Chrome 插件开发实战:一键把当前页面存为 Markdown》。从 manifest.json 写到 Chrome Web Store 审核通过,一个具体例子走完整流程。
如果你只是想"给自己用"或"在团队里用",加载已解压的扩展就够了,不用走商店。
写在最后
Chrome 插件的入门成本比想象的高,但天花板比想象的低。
- 一周内可以做一个能解决具体问题的小工具
- 几乎所有能力都受限于 Chrome 提供的 API
- 真要做好,需要和 Chrome 的限制周旋
但反过来想:
- 一次开发,Chrome 用户都能用
- 不用考虑跨平台
- 不用考虑安装包的更新
- 不用考虑应用商店的审核(Edge 商店审核宽松得多)
这是一件"小而美"的事。适合做出来给自己用,做出来给团队用,做出来给社区用。
发表评论