# 浏览器扩展 架构模板 > **代表产品**: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. 可复用要点 - 💡 **当你「寄生」在你不可控的环境里时,把触碰那个环境的部分做到最薄。** 内容脚本越简单越安全——这等同于「依赖外部系统时,把适配层做薄、把核心逻辑护在自己这边」。 - 💡 **最小权限不是安全条款,是产品战略。** 你索取的每一项能力都在透支信任、放大风险面。先问「不要这个权限我能不能做到」。 - 💡 **沿「隐私敏感度」而不是「实现方便度」来切分客户端与服务端。** 「该不该把这条数据发出去」永远优先于「这样写方不方便」。 - 💡 **把「会随时间腐烂的数据」当成需要持续保鲜的工程,而非一次性灌入。** 优惠券如此,任何「外部世界一变就过时」的数据(价格、库存、对手页面结构)都如此。 - 💡 **当商业模式建立在某一笔技术动作上(这里是归因),那笔动作的合法与道德边界,就是你架构里最硬的约束。** 技术能做到,不代表应该做——有时道德红线就是系统的硬性需求。 - 💡 **警惕「你赖以运行的地基会自己移动」。** 平台政策、第三方页面结构都不在你掌控内;架构上要把对它们的依赖收拢、隔离、可替换。 ## 🎯 随堂检验 --- ## 参考原型与延伸阅读 > 本模板基于以下**官方文档**与**真实开源扩展**整理。 **📖 官方文档:** - [MDN: Anatomy of a WebExtension](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension) — 内容脚本与后台脚本的职责分离及消息通信。 - [Chrome: Migrate to a service worker (Manifest V3)](https://developer.chrome.com/docs/extensions/develop/migrate/to-service-workers) — MV3 后台被 service worker 取代、按需运行、状态需持久化。 **🔧 开源原型(可直接读代码):** - [gorhill/uBlock](https://github.com/gorhill/uBlock) — 经典开源扩展,体现内容过滤 / 页面注入与隐私保护的工程实践。 --- > 📌 一句话记住浏览器扩展:**它是「寄居在别人页面里、却能看到用户一切」的特殊存在——所有架构取舍,最终都在回答『如何用最小的权限、最克制的数据,把这层注入能力做得既有用、又让人信得过』。**