浏览器扩展 架构模板
代表产品:Honey、Grammarly、各类浏览器插件(广告拦截、密码管理、网页标注) 一句话定位:在用户浏览「别人的网页」时,从浏览器内部往页面里注入一层额外能力,并靠这个能力位置变现。
1. 一句话定位
一个浏览器扩展 = 一段「寄生」在别人网页里的代码 + 一个常驻浏览器、跨标签页协调的后台 + 一套在你自己服务器上的数据与变现引擎。
架构上最反直觉的一点:你没有自己的页面。你的「前端」运行在用户随时会访问的、你无法控制的任意网站上(购物站、邮箱、文档),受浏览器扩展平台的沙箱模型严格约束。于是整套架构的核心矛盾是:你能看到用户几乎所有的浏览行为(巨大的能力),但平台、用户、法律都在死死盯着你『到底碰了什么』(巨大的信任与隐私边界)。 架构做得好不好,本质上是在回答「如何在最小的权限、最克制的数据收集下,把这层注入能力做得既有用又可信」。
2. 业务本质:它在解决什么问题
用户要的是在做某件事的当下,不离开当前页面,就多一项帮手能力:
- 购物返现类(Honey):结账时自动帮我找遍全网优惠券、一键试出最省的那张,顺便给我返现;
- 写作辅助类(Grammarly):我在任何输入框打字时,实时帮我挑错、改写;
- 工具增强类:拦广告、存密码、给网页做标注/翻译。
共同点:它的价值发生在「用户正在另一个产品里操作」的瞬间。它不抢用户去自己的 App,而是贴着用户已有的工作流。
钱从哪来(以返现类为典型):
- 联盟营销分成(affiliate):用户经你点击/下单,商家付给你一笔佣金,你抽一部分返给用户、留一部分当利润;
- 订阅 / 高级功能(写作类常见:基础免费,高级语法、改写、查重收费);
- 企业版(团队管理、合规、私有词库)。
关键事实:返现类产品的整个商业模式,建立在「归因(attribution)」这一笔技术动作上——能不能正确、合规地证明『这笔订单是我带来的』,直接决定有没有收入。 这一条会反复影响后面的架构与道德边界。
3. 核心需求与约束
功能性需求(系统要能做什么):
- [ ] 识别当前页面:判断「用户现在是不是在某个支持的商家的结账页 / 某个可增强的输入框」。
- [ ] 注入与读写页面:往页面里插入 UI(按钮、提示框),读写页面的 DOM(读出价格、自动填入优惠码)。
- [ ] 跨标签页 / 跨会话的状态:用户登录态、当前正在追踪的订单、待结算的返现。
- [ ] 与后端通信:查优惠券库、查商家规则、上报归因、同步返现账本。
- [ ] 弹窗 / 独立 UI:点扩展图标弹出的面板(看返现余额、账户、设置)。
- [ ] 数据采集管线:持续收集、验证、更新优惠券和商家规则(爬取 + 众包)。
非功能性需求 / 质量属性(这才是架构的主战场):
| 质量属性 | 目标 | 为什么对这类系统重要 |
|---|---|---|
| 可信 / 隐私可证明 | 最高优先级 | 你能看到用户几乎所有网页,一旦被发现偷传数据,产品当天就死。 |
| 页面零破坏 | 不拖慢、不弄乱宿主页面 | 你是客人,搞砸了别人的购物车,用户卸载你而不是卸载淘宝。 |
| 注入响应速度 | 结账页出现后毫秒级识别 | 慢一步用户已经付完款,优惠和归因都来不及。 |
| 平台合规 | 严格符合扩展平台政策 | 政策违规 = 直接下架,这是悬在头顶的剑。 |
| 数据新鲜度 | 优惠券「不过期、能用」 | 试了五张全是失效券,用户对你的信任归零。 |
| 可用性 | 后端高可用 | 后端挂了,扩展在结账页转圈,等于在用户最关键时刻掉链子。 |
关键约束(不可逾越的边界):
- 🔴 运行在扩展沙箱里,能力由平台定义、随时可被收回。 你能用哪些 API、能拿哪些权限、脚本生命周期多长,全是平台说了算。
- 🔴 平台权限模型会演进(且越来越严)。 平台一次政策升级(收紧后台常驻、收紧网络拦截能力、强制权限最小化),可能让你整套架构推倒重来——这是头号平台风险。
- 🔴 内容脚本与宿主页面共享同一个页面环境,但又被刻意隔离。 它能读 DOM,却(在隔离机制下)碰不到页面自己的脚本变量;它的能力比普通网页大,又远小于一个原生程序。
- 🔴 「能看到一切」本身就是最大的风险面。 数据收集的边界不是技术问题,是生死问题。
- 法律 / 道德边界:归因的获取方式一旦越界(覆盖掉别人带来的归因),会引发法律与口碑风险。
4. 架构全景图
用户浏览器 │ 你的服务器(后端)
┌───────────────────────────────────────────────┐ │ ┌──────────────────────────────────┐
│ │ │ │ │
│ 宿主网页(购物站 / 邮箱 / 文档——你不可控) │ │ │ 接入层 API(鉴权 / 限流) │
│ ┌─────────────────────────────────────┐ │ │ └───────────────┬──────────────────┘
│ │ 内容脚本(Content Script) │ │ │ │
│ │ • 注入到页面、读写 DOM │ │ │ ┌────────────┼─────────────┐
│ │ • 识别商家 / 识别输入框 │ │ │ ▼ ▼ ▼
│ │ • 自动填券 / 注入提示 UI │ │ │ ┌────────┐ ┌─────────┐ ┌──────────┐
│ │ • 【只做与本页 DOM 相关的事】 │ │ │ │优惠券库 │ │商家规则库│ │用户账户 │
│ └───────────────┬─────────────────────┘ │ │ │/ 词库 │ │/ 归因规则│ │/ 返现账本│
│ │ 消息(message passing) │ │ └────┬───┘ └─────────┘ └──────────┘
│ ▼ │ │ │
│ ┌─────────────────────────────────────┐ │ │ ▼
│ │ 后台脚本 / 常驻进程(Background) │◀───┼───┼──── 数据采集管线
│ │ • 跨标签页 / 跨会话状态 │ │ │ ┌──────────────────────────┐
│ │ • 唯一的对外网络出口 ───────────────┼────┼───┼───▶│ 爬取器 + 众包提交 + 人工审核 │
│ │ • 管理登录态、协调归因上报 │ │ │ │ → 验证优惠券是否仍有效 │
│ └───────────────┬─────────────────────┘ │ │ └──────────────────────────┘
│ │ │ │
│ ▼ │ │
│ ┌─────────────────────────────────────┐ │ │
│ │ 弹窗 / 独立 UI(Popup) │ │ │
│ │ • 看返现余额、账户、开关设置 │ │ │
│ └─────────────────────────────────────┘ │ │
└───────────────────────────────────────────────┘ │
浏览器沙箱边界(平台说了算) 信任边界(数据离开用户机器)灵魂部件不是某一个框,而是那条贯穿「内容脚本 → 后台脚本 → 后端」的窄通道:页面里发生的事,要经过一道道收窄(只读必要的 DOM、只由后台一个出口联网、只上报必要字段),才能变成后端的一次查询或一笔归因。架构的全部艺术,在于这条通道每一段都尽量「少碰、少传、少存」。
5. 组件职责
逐个说明每个关键部件做什么 + 为什么需要它(没有「为什么」的部件就是过度设计)。
- 内容脚本(Content Script):被平台注入到宿主页面里,是唯一能直接读写当前页 DOM 的部分。负责识别当前页(这是不是某商家的结账页?这是不是一个可增强的输入框?)、注入 UI(优惠提示、改写建议)、以及在页面上执行动作(把优惠码填进输入框、点应用)。为什么需要:只有它能触碰宿主页面;扩展的「价值发生在别人页面上」这件事,物理上只能由它来兑现。但它应该尽量「笨」——只做与本页 DOM 强相关的事,别把业务逻辑和密钥塞进来(见决策 1)。
- 后台脚本 / 常驻进程(Background):扩展的「大脑」与唯一对外网络出口。它持有跨标签页、跨会话的状态(登录态、当前追踪的订单、待结算返现),协调各个标签页里的内容脚本,统一与后端通信、统一上报归因。为什么需要:内容脚本随页面刷新就销毁、彼此隔离,需要一个「活得更久、看得更全」的角色来保存状态、收口网络请求。把联网集中到这里,既便于统一鉴权限流,也便于把「碰了哪些网络」这件事审计清楚。
- 弹窗 / 独立 UI(Popup):用户点扩展图标弹出的面板,展示返现余额、账户、设置开关。为什么需要:这是扩展自己的、可控的一块界面,适合放「需要用户主动来看/操作」的内容;它和注入到宿主页的 UI 是两回事,不要混。
- 后端:优惠券库 / 词库:存放海量优惠券、商家规则(写作类则是语法规则 / 词库)。为什么需要:这些数据量大、更新频繁、需要被全体用户共享和快速检索,放客户端既塞不下也无法及时更新(见决策 4)。
- 后端:商家规则库 / 归因规则:每个商家的页面长什么样、优惠码填在哪个输入框、归因怎么记。为什么需要:商家页面千变万化且经常改版,把「怎么识别、怎么操作」做成后端可下发的规则/配置,才能不发新版扩展就适配商家改版(见决策 4)。
- 后端:用户账户 / 返现账本:用户身份、累计返现、提现流水。为什么需要:返现是钱,必须强一致、可审计、不能错账;这类数据天然属于服务端。
- 数据采集管线(爬取 + 众包 + 验证):持续地从各处收集优惠券、接收用户众包提交、并反复验证「这张券现在还能不能用」。为什么需要:优惠券的核心价值是「真能用」,而它天然会过期、被商家撤下;没有一条持续刷新、持续验证的管线,优惠券库会迅速腐烂(见决策 5)。
6. 关键数据流
挑 2–3 个最能体现这个系统特点的场景。
场景一:结账页自动找券 + 应用最优 + 记录归因(返现类最核心的路径)
1. 用户进入某商家结账页
──▶ 内容脚本检测 URL / 页面特征:命中「支持的商家」
2. 内容脚本 ──消息──▶ 后台脚本:「用户在商家 X 的结账页,帮我要券」
3. 后台脚本 ──▶ 后端:查 商家X 当前可用优惠券列表 + 该商家的页面操作规则
(后端:从优惠券库筛出未过期、适用本订单的券,按预估折扣排序返回)
4. 后台脚本 ──消息──▶ 内容脚本:把券列表 + 操作规则下发
5. 内容脚本在页面上「依次试券」:
填入券码 → 点应用 → 读取页面上的新总价 → 记录这张券省了多少
⟲ 循环试完候选券(或试到足够好就停)
6. 内容脚本应用「省得最多的那一张」,在页面上提示用户「已为你省下 ¥XX」
7. 若用户继续下单 ──▶ 后台脚本记录归因(这单由本扩展促成)──▶ 后端返现账本登记一笔「待结算返现」
(商家后续确认订单有效后,该笔返现转为「可提现」)注意两点:① 「试券」这种与页面强耦合、要反复读 DOM 的脏活,只能在内容脚本里做;而「哪些券值得试、试的顺序」这种业务判断,尽量由后端算好下发。② 第 7 步的归因是整个商业模式的命脉,也是道德红线所在(见第 10 节)。
场景二:写作辅助——任意输入框的实时增强
用户在「任意网站的任意输入框」打字
──▶ 内容脚本监听输入,识别出这是一个可增强的编辑区
──▶ 内容脚本把「待检查的文本」交给后台脚本
──▶ 后台脚本 ──▶ 后端:做语法/改写分析(重模型放后端)
──▶ 结果回传 ──▶ 内容脚本在输入框旁注入「建议下划线 / 改写卡片」
──▶ 用户点采纳 ──▶ 内容脚本把修改写回输入框的 DOM
⚠️ 隐私要点:用户在「任意输入框」打的字,可能是密码、私信、病历。
架构上必须明确:哪些字段绝不采集(密码框、标注为敏感的字段),
传输的是「检查所需的最小文本」,而不是「页面上看到的一切」。场景三:优惠券数据的采集与保鲜(后端侧的持续流程)
来源 A:爬取器定时抓取各优惠站 / 商家活动页 ─┐
来源 B:用户在结账页众包提交「这个码能用」 ─┼─▶ 候选优惠券池
来源 C:合作渠道导入 ─┘ │
▼
验证器:用规则尝试校验有效性
(是否过期 / 是否有最低消费 / 是否地区限定)
│
┌───────────────┼───────────────┐
▼ ▼ ▼
标记有效 标记失效 存疑→人工审核
│
▼
进入「可下发」优惠券库 ──▶ 供场景一查询这条管线的存在,是因为优惠券的价值会随时间衰减:今天能用的码明天可能就撤了。新鲜度不是一次性问题,而是要持续投入的「保鲜」工程。
7. 数据模型与存储选择
核心实体:用户 ─ 账户/返现账本 ─ 返现流水;商家 ─ 优惠券 / 页面操作规则;归因事件;众包提交。写作类则把「优惠券/商家规则」换成「语法规则 / 用户词库」。
| 数据 | 存储类型 | 为什么 |
|---|---|---|
| 用户 / 账户 / 返现账本 | 关系型 | 涉及钱,要事务、强一致、可审计,绝不能错账 |
| 返现 / 提现流水 | 关系型 / 追加日志 | 金额流水只追加、可对账,需要严格的一致性与留痕 |
| 优惠券库(海量、频繁更新) | 文档型 + 检索索引 | 数量大、结构灵活(不同商家字段不同)、要按商家快速筛选 |
| 商家页面操作规则 | 文档型 / 可下发配置 | 本质是「下发给客户端的配置」,要能不发新版就更新 |
| 热点商家的可用券 | 内存级 KV 缓存 | 结账瞬间要毫秒级返回,且同一商家被反复查询(读多写少) |
| 归因事件 / 用量埋点 | 时序 / 列存 | 海量、按时间聚合、用于对账与分析 |
| 客户端本地状态(登录态、设置) | 浏览器本地存储 | 体积小、随用户在本机,不该也不必上传服务器 |
教学点:注意「客户端该存什么」这一行——它是隐私边界在数据模型上的体现。 凡是「不传到服务器也能工作的」状态(开关、偏好、临时追踪),就留在用户本机;只有「必须共享 / 必须强一致(钱)」的数据才上服务器。能少存一份用户数据在你服务器上,你的风险面就小一分。
8. 关键架构决策与权衡 ⭐
(本模板最值钱的一节。)
决策 1:逻辑放内容脚本,还是放后台脚本 / 后端?(扩展架构的第一性问题)
- 全塞内容脚本:能直接操作页面,看起来「就近、方便」。但代价极大:① 内容脚本随页面刷新就销毁、彼此隔离,放不住状态;② 它和宿主页面共处,逻辑和密钥暴露在一个充满敌意的环境里,容易被宿主页或恶意脚本窥探/干扰;③ 业务逻辑写死在客户端,改一次得发一次新版,迭代极慢。
- 内容脚本只做「碰 DOM 的脏活」,业务判断上移到后台脚本与后端:内容脚本只负责「读页面、填页面、注入 UI」;「该不该填、填哪张、归因怎么记」交给后台/后端。
- 取向:坚决让内容脚本越薄越好。 它是你伸进别人页面的「手」,只该做手该做的事;「大脑」放在后台脚本(跨页状态)和后端(业务规则)。代价是要设计内容脚本↔后台↔后端之间的消息协议、多一跳通信延迟。但这是值得的:注入点越简单,越安全、越好维护、越能快速适配商家改版。
决策 2:权限最小化——能不要的权限,一个都别要
- 申请「访问所有网站 + 读所有数据」的大权限:开发省事,什么页面都能插手。但代价是:① 平台审核更严、上架更难;② 用户安装时看到「可读取你在所有网站的数据」会犹豫甚至拒装;③ 一旦你被攻破,攻击者顺势拿到的也是这套大权限,风险面被你自己撑到最大。
- 按需、可渐进申请权限:只在用户真正用到某商家时,才请求对该站点的权限;能用窄 API 就不用宽 API。
- 取向:最小权限是这类产品的立身之本,不是可选项。 你索取的每一项权限都在透支用户信任、扩大风险面、增加平台风险。代价是实现更麻烦(要处理「权限还没拿到」的状态、引导用户授权),但这正是「可信」这一头号质量属性的架构落地方式。
决策 3:客户端做多少,后端做多少?
- 偏客户端:把识别商家、筛券、算折扣都放本地。优点是离线也能跑、不依赖网络、不把浏览行为发给服务器(隐私更好)。代价是逻辑更新慢(要发版)、客户端能力受限、复杂计算扛不住。
- 偏后端:客户端只采集最小输入、把判断交给服务器。优点是逻辑随时可更新、能力强、适配商家改版快。代价是多了一次「把数据发给服务器」的隐私暴露,且强依赖网络与后端可用性。
- 取向:沿「隐私敏感度」这条线切。 不敏感、又需要频繁更新规则的(优惠券筛选、商家适配)放后端;一碰就涉及隐私的(用户在输入框打了什么、访问了哪些站)尽量在客户端处理、只上传「完成任务所必需的最小片段」。「该不该把这条数据发出去」永远比「这样实现方不方便」优先级高。
决策 4:商家适配规则——硬编码进扩展,还是后端可下发?
- 硬编码:每个商家的页面识别、填券逻辑都写死在扩展代码里。简单直接,但商家一改版你就失效,且只能靠发新版修复(还要等平台审核、等用户更新)。
- 后端可下发配置/规则:把「如何识别商家、优惠码填哪个框、归因怎么记」做成后端下发的数据,扩展启动时拉取。
- 取向:规模一上来(支持几十上百个商家)就必须可下发。 否则你会被「商家随时改版」拖死。代价是要设计一套规则的描述方式与下发机制、客户端要能安全地执行这些下发规则(注意:下发的是「配置/选择器」,不是「任意可执行代码」,否则等于给自己开了远程注入的后门)。
决策 5:优惠券新鲜度——实时验证,还是后台批量保鲜?
- 用户结账时实时去验证每张券:最准,但慢(用户在等)、且把验证压力堆在最关键的时刻。
- 后台管线持续批量验证、给券打「有效/失效」标签,结账时只取已验证为有效的:快,但存在「刚失效还没被复检」的窗口。
- 取向:以后台保鲜为主,实时为辅。 后台管线持续把券池刷新干净;结账时优先用「近期验证过有效」的券,并把「试券时发现失效」这一信号回流给管线(等于用真实结账行为帮你保鲜)。代价是要运营一条持续的数据管线,以及接受一个小的失效窗口——但比起「让用户在结账页干等验证」,这个取舍划算得多。
决策 6:归因如何实现,以及边界在哪?(技术与道德同时存在的决策)
- 激进做法:不管这笔流量原本是不是别人(别的推广者、别的渠道)带来的,一律覆盖成「我带来的」以最大化佣金。技术上能做,短期收入高。
- 克制做法:只在「确实由本扩展促成」时记归因;不去覆盖用户已有的、来自他人的归因。
- 取向:必须选克制。 覆盖他人归因(俗称「归因劫持」)即便技术可行,也会带来真实的法律风险、合作方反制、以及一旦曝光的口碑崩塌——而口碑对一个「能看到你一切浏览行为」的产品是生命线。这是架构决策里少见的、道德约束直接成为硬约束的例子:商业模式必须建在站得住脚的归因之上,否则整座大厦的地基是违法的。
9. 规模化与瓶颈
和普通网站不同:这类系统的「规模」压力,既来自用户量,也来自「要适配的外部世界(商家/网站)的数量与变化频率」。
- 第一个瓶颈:平台政策与权限模型的变化。(这是最特殊、最容易被低估的瓶颈) 破解:① 架构上把「依赖某个平台特性」的部分收拢、隔离,使其可替换;② 不把核心能力压在某个随时可能被收紧的 API 上;③ 持续跟踪平台政策,提前迁移。这不是流量问题,而是『你赖以运行的地基随时会动』的问题——再多服务器也扩不出来。
- 第二个瓶颈:商家/网站越多越杂,适配规则的维护爆炸。 破解:① 适配规则后端可下发(决策 4),把「修复」从「发版」降级为「改配置」;② 用更通用的页面识别策略减少逐个商家硬编码;③ 把众包/反馈接入,让真实使用数据帮你发现失效的适配。
- 第三个瓶颈:结账高峰期的后端查询(查券/查规则)被打满。 破解:① 热点商家的可用券放内存级 KV 缓存(读多写少,极适合缓存);② 优惠券库的检索索引优化;③ 把「能在客户端判断的」尽量下沉,减少后端往返。
- 第四个瓶颈:数据采集管线跟不上优惠券的腐烂速度。 破解:① 验证器水平扩展;② 按「商家热度」分级保鲜(热门商家高频复检,冷门的低频);③ 用真实结账反馈反哺验证。
- 返现账本的一致性不是瓶颈但是高压区:涉及钱,宁可慢也要对。它通常不是性能瓶颈,而是「绝不能错」的正确性红线——用关系型存储 + 严格对账守住。
10. 安全与合规要点
这是这类系统最重的一节,因为它的能力天然逼近隐私的极限。
- 🔴 「能看到一切」是最大的攻击面与责任面。 扩展能观察用户几乎所有网页。架构上必须把「采集边界」当成一等公民:明确列出绝不采集的内容(密码框、支付卡号、明确敏感的字段、与功能无关的页面),传输「完成任务所必需的最小数据」,而不是「方便起见把页面都传走」。这条边界要能对用户、对平台讲清楚、可审计。
- 🔴 扩展的超强权限 = 一旦被攻破,后果被放大。 因此:权限最小化(决策 2)、后台脚本作为唯一网络出口便于审计、下发的只能是「配置」而非「任意可执行代码」(否则等于自带远程代码注入漏洞)、对后端通信加密。
- 🔴 归因的法律与道德边界。 归因劫持(覆盖他人带来的归因)有真实法律风险;架构与产品策略上必须守住「只记真正由自己促成的归因」(决策 6)。这不仅是合规,更是这类产品的信任根基。
- 内容脚本与宿主页面的隔离边界。 内容脚本要防止被宿主页面的恶意脚本利用或欺骗;注入的 UI 不应把敏感数据暴露在宿主页能读到的地方。
- 数据收集的「知情与同意」。 收集了什么、用来干什么、是否售卖/共享,必须透明、可关闭、可删除——尤其当变现本身就依赖用户数据时,边界更要清晰。
- 平台风险即合规风险。 平台政策(数据使用、权限、变现方式)本身就是你必须遵守的「法律」,违反 = 下架。
11. 常见误区 / 反模式
- ❌ 把业务逻辑、密钥一股脑塞进内容脚本 → ✅ 内容脚本只做「碰 DOM 的脏活」,逻辑上移到后台与后端;注入点越薄越安全(决策 1)。
- ❌ 为图省事申请「访问所有网站」的大权限 → ✅ 最小、按需、可渐进申请;每一项权限都在透支信任、放大风险(决策 2)。
- ❌ 把「方便实现」凌驾于「该不该传这条数据」之上 → ✅ 隐私敏感的数据尽量留在客户端,只上传完成任务的最小片段(决策 3)。
- ❌ 商家适配逻辑硬编码、只能靠发版修复 → ✅ 适配规则后端可下发,把修复从「发版」降级为「改配置」(决策 4)。
- ❌ 把整个优惠券库塞进客户端图省一次请求 → ✅ 海量、频繁更新、需共享的数据放后端,客户端只拿当前需要的(决策 4/5)。
- ❌ 下发「可执行代码」给扩展去跑 → ✅ 只下发配置/选择器这类数据;下发可执行代码等于给自己装了远程注入后门。
- ❌ 为多赚佣金而覆盖他人归因 → ✅ 只记真正由自己促成的归因;归因劫持是法律与口碑的双重地雷(决策 6)。
- ❌ 把注入 UI 做得喧宾夺主、拖慢宿主页 → ✅ 你是客人,克制注入、绝不破坏宿主页面的核心流程。
12. 演进路线:MVP → 成长期 → 成熟期
| 阶段 | 规模量级 | 架构长什么样 | 此时该操心什么 |
|---|---|---|---|
| MVP | 验证想法,1 个或几个商家 | 一个薄内容脚本 + 一个后台脚本 + 一个简单后端;优惠券库靠手工维护;只申请所需站点的最小权限;归因走最直接的合规方式 | 先验证「用户真的会用、佣金模型真的成立」,别一上来就建采集管线 |
| 成长期 | 几十~上百商家,百万级用户 | 商家适配规则改为后端可下发;搭建数据采集管线(爬取 + 众包 + 验证);热点券进缓存;返现账本上事务与对账;补全弹窗 UI 与账户体系 | 把适配从「发版」解耦,守住数据新鲜度,稳住归因合规 |
| 成熟期 | 海量商家 / 联盟网络,千万级用户 | 完整的返现账本 + 联盟网络对接 + 众包数据闭环;按热度分级的保鲜管线;面向平台政策变化的可替换架构;严格的隐私边界与审计能力 | 平台风险与合规、数据信任、归因的规模化与合法性、采集管线的成本 |
13. 可复用要点
- 💡 当你「寄生」在你不可控的环境里时,把触碰那个环境的部分做到最薄。 内容脚本越简单越安全——这等同于「依赖外部系统时,把适配层做薄、把核心逻辑护在自己这边」。
- 💡 最小权限不是安全条款,是产品战略。 你索取的每一项能力都在透支信任、放大风险面。先问「不要这个权限我能不能做到」。
- 💡 沿「隐私敏感度」而不是「实现方便度」来切分客户端与服务端。 「该不该把这条数据发出去」永远优先于「这样写方不方便」。
- 💡 把「会随时间腐烂的数据」当成需要持续保鲜的工程,而非一次性灌入。 优惠券如此,任何「外部世界一变就过时」的数据(价格、库存、对手页面结构)都如此。
- 💡 当商业模式建立在某一笔技术动作上(这里是归因),那笔动作的合法与道德边界,就是你架构里最硬的约束。 技术能做到,不代表应该做——有时道德红线就是系统的硬性需求。
- 💡 警惕「你赖以运行的地基会自己移动」。 平台政策、第三方页面结构都不在你掌控内;架构上要把对它们的依赖收拢、隔离、可替换。
🎯 随堂检验
- A尽量多要,以备不时之需
- B最小权限:能不要的权限坚决不要
- C要多少无所谓,反正用户会同意
参考原型与延伸阅读
本模板基于以下官方文档与真实开源扩展整理。
📖 官方文档:
- MDN: Anatomy of a WebExtension — 内容脚本与后台脚本的职责分离及消息通信。
- Chrome: Migrate to a service worker (Manifest V3) — MV3 后台被 service worker 取代、按需运行、状态需持久化。
🔧 开源原型(可直接读代码):
- gorhill/uBlock — 经典开源扩展,体现内容过滤 / 页面注入与隐私保护的工程实践。
📌 一句话记住浏览器扩展:它是「寄居在别人页面里、却能看到用户一切」的特殊存在——所有架构取舍,最终都在回答『如何用最小的权限、最克制的数据,把这层注入能力做得既有用、又让人信得过』。