1599 字
约 5 分钟
5
「宿主插件双线程」通用架构笔记
「宿主插件双线程」通用架构笔记
主题抽象:当宿主平台强制把一个插件/扩展的运行环境拆成"能操作宿主"与"能联网/有UI"的两个隔离侧时,如何设计架构。 适用范围:Figma 插件、Chrome/浏览器扩展、桌面应用扩展(OBS/IDE)、Electron 插件、甚至 Webview 应用 —— 只要是"分叉的两侧必须靠消息桥沟通"的环境都适用。 本笔记刻意不与任何具体项目绑定,讲的是这条规律本身;文末附"如何套用"。
一、先认识问题的普遍形态
很多宿主平台在运行"插件/扩展"时,会强制拆分两个隔离环境:
| 侧 A:操作宿主侧 | 侧 B:界面/网络侧 |
|---|---|
| 能力:能操作宿主本身(画布/文档/宿主API) | 能力:有真实 DOM,能联网 fetch,可跑第三方 |
| 限制:往往没有网页、不能直接联网 | 限制:碰不到宿主内部对象/API |
| 身份:常称 "main"/"background" | 身份:常称 "UI"/"content"/"front" |
典型矛盾:很多功能天然需要"既联网(调后端/AI/第三方),又能改动宿主(把结果写进宿主的画布/文档/状态)"。但宿主平台强制这两件事不在一侧。于是架构必须:拆分职责 + 用一座显式消息桥连通两侧。
一句话:不是我们想拆,是宿主逼我们拆。架构的好坏在于——怎么把桥设计得清晰、可校验。
二、什么时候用这套架构(普适决策信号)
用"双线程 + 消息桥"的判据,不是看技术栈,而是看三件事:
- 宿主是否强制隔离?
- 是(Figma/Chrome扩展/桌面插件/Electron renderer+main)→ 大概率要用
- 否(普通单页 Web App、纯后端)→ 别为拆而拆
- 功能是否同时需要"联网 + 操作宿主"?
- 是需要(调 AI、拉数据、然后改宿主状态)→ 双线程的典型受益场景
- 只需之一 → 可考虑简化
- 是否存在多客户端 / 换供应商 / 复用的需求?
- 有 → 更要把"重活"收到独立一侧,减少重复
原则一句话:"宿主强制隔离 → 用;只是想要架构漂亮 → 不必然。"
三、通用架构骨架(与具体平台无关)
┌─ 宿主插件 ───────────────────────────────┐
│ 侧B:UI/网络 侧A:操作宿主
│ ·渲染界面、收输入 ◄———消息桥(postMessage)———→ ·收指令
│ ·调远端服务(联网) ·调用宿主API写结果
│ ·把结果/请求发过桥 ·把进度/状态传回
└──────┬──────────────────────────────────────┘
│ 网络
┌───▼───────────┐
│ 独立后端/服务 │ ← 重活集中地:AI/存储/编排/第三方
└───────────────┘
不变的四个角色:
- 宿主操作侧(A):唯一能真正改动宿主结果的一侧。
- 界面/网络侧(B):唯一能联网、有 UI 的一侧。
- 消息桥:两侧唯一通信通道;消息格式就是"契约"。
- 独立服务层(可选但强烈建议):把"重活"从两侧里抽出来,集中到后端/后台,避免塞进薄侧。
四、设计要点(普适正确做法)
- 契约先行、先定义再实现:桥是"最难查错"的边界。先定义两侧都版本化的消息 schema(type + payload + error + correlation),再写任何功能。
- 职责单一,别让消息满天飞:一条主路径 + 少量明确旁路。两侧各只做自己该做的。
- 重活下沉到独立服务层:联网后的复杂处理、第三方、持久化,最好抽到后端/后台进程,前端/宿主侧保持"薄"。
- 桥要可校验:两侧用同一套 schema 校验消息;协议升级要版本号、能做迁移。
- 错误要有显式回传:跨桥的失败要能被另一侧明确感知,不要静默丢。
五、通用反模式(任何平台都别踩)
- ❌ 两侧各自维护一份"消息格式"的猜测,无共享 schema → 一旦漂移,静默失败、极难查。
- ❌ 把所有重逻辑塞进"界面/网络侧" → 换供应商/换客户端要改多处,且 UI 侧一卡全卡。
- ❌ 忽视"能联网 ≠ 能操作宿主" → 功能设计出来却落不了地。
- ❌ 用"重启/手动"兜底桥不同步 → 正确做法是让契约自动校验、显式失败。
- ❌ 把桥当"电话粥",大量无关消息来回 → 不可调试、性能差。
六、选型速查
要做宿主上的插件/扩展
├─ 宿主强制隔离联网与宿主API
│ ├─ 功能只需"联网"或只需"动宿主" → 可只走一侧,简化
│ └─ 功能两者都要 / 要换供应商或多端
│ ├─ 高频交互 → 加"乐观更新 + 后台重建"处理状态
│ ├─ 消息格式多变 → 加共享 schema + 版本号
│ └─ 重活多 → 抽独立服务层
└─ 宿主不隔离 / 非插件形式 → 普通单线程,别过度设计
七、如何套用到你的具体项目
把上面的骨架映射到任何平台,只换"宿主API名"和"消息语义":
- Figma 插件 → 操作侧=Figma 主线程 API;网络侧=UI 面板
- Chrome 扩展 → 操作侧=background/service worker;网络侧=content/popup
- Electron → 操作侧=main process;网络侧=renderer
- 桌面/IDE 插件 → 操作侧=宿主 SDK;网络侧=插件面板
映射时只做三件事:① 分清哪侧能联网、哪侧能操作宿主;② 定义桥的消息契约;③ 把重活抽到独立服务层。
八、相关
- 主题关联:
缓存失效与改了就更新、模型任务分流(理解 vs 生成) - 用途提示:本笔记是"宿主插件双线程"的母版;实际某个项目里的细节(文件名/API 名)看该项目自己的
learning文档。
评论
0 条
还没有评论,先写一条吧。