Skip to main content

Design Extension

  • Extension / Plugin / Add-on - 扩展、插件、附加组件。
  • 目标:在不修改核心产品代码的情况下,让第三方或业务侧扩展能力、集成系统、自动化流程、定制 UI。
  • 常见形态:插件、hook、middleware、event、callback、脚本、WASM、module、driver、provider、connector。
  • 设计扩展能力的关键不是“让用户执行代码”,而是定义清晰的边界、生命周期、权限、数据模型和兼容策略。

扩展能力分类

类型说明典型例子适合
Plugin / Add-on安装到宿主应用内,调用宿主 APIBrowser extension、Figma Plugin、VS Code Extension产品生态、UI/工作流定制
Hook / Callback宿主在关键点调用扩展逻辑Git hooks、Quick Look callbacks、Webhook handler生命周期插入点、轻量定制
Middleware请求/事件经过一组可组合处理器HTTP middleware、RPC interceptor、Nginx phases认证、日志、限流、转换
Event / PubSub宿主发布事件,扩展订阅处理Webhook、EventBridge、IDE events解耦通知、多消费者
Script用户脚本在受控运行时执行Figma JS plugin、Lua plugin、SQL UDF快速自动化、低门槛扩展
Module / Native Plugin编译成宿主可加载模块Nginx module、Kernel module高性能、底层能力
WASM Extension通过 WASM 沙箱执行扩展Envoy WASM filter、Proxy-Wasm高隔离、跨语言、高性能
Provider / Driver实现宿主定义的接口Storage driver、Auth provider、Payment provider替换后端能力、对接外部系统
Connector / Integration连接第三方系统SaaS connector、ETL connector数据同步、系统集成
Theme / Resource Pack扩展样式、资源、模板Editor theme、Game modUI 外观、内容包

典型系统对照

系统扩展形态入口隔离/权限特点
Browser WebExtensionsManifest + background/content script/APImanifest.json、content script、service workerpermissions、host permissions、extension process跨浏览器生态,强权限声明
Chrome ExtensionsManifest V3 + extension APIsservice worker、content scripts、action、devtools权限、CSP、Chrome Web Store 审核强调安全、声明式 API、后台生命周期受限
Figma PluginJavaScript + HTML UI + Plugin API用户主动运行 plugin command文件 API 权限、iframe UI、用户触发短生命周期,不支持后台常驻
macOS Quick LookGenerator plugin + UTI + callbacksGeneratePreviewForURLGenerateThumbnailForURL系统加载、bundle 配置专注文件预览/缩略图,callback 模型清晰
Nginx ModuleC module + phase/filter/config directivesHTTP phase、filter、directive进程内 native code,无强沙箱性能高,但必须遵守非阻塞、内存池、reload 约束
VS Code ExtensionNode.js extension host + contribution pointspackage.json contributes、activation eventsextension host、workspace trust、capabilitiescontribution point 很完整,适合 IDE 生态
Envoy WASMProxy-Wasm ABIHTTP/network filterWASM sandbox、ABI 限制适合高性能网关扩展
WordPress PluginPHP plugin hooks/options/admin UIactions、filters、shortcode进程内 PHP,依赖审核/权限生态大,但安全和兼容治理压力大

扩展点模型

Declarative Extension Point

扩展通过配置声明能力,宿主解释执行。

例子:

  • Browser extension manifest permissions / content scripts。
  • VS Code contributes.commands / contributes.languages
  • Kubernetes CRD / Controller registration。

优点:

  • 容易校验、审核、静态分析。
  • 权限边界清晰。
  • 兼容性更容易维护。

缺点:

  • 表达能力有限。
  • 高级逻辑仍需要脚本或 native API。

Imperative Extension Point

扩展提供代码,宿主在运行时调用。

例子:

  • Hook callback。
  • Middleware function。
  • Plugin API method。
  • Native module handler。

优点:

  • 灵活、表达力强。
  • 适合复杂业务和集成。

缺点:

  • 安全、性能、兼容性更难控制。
  • 容易把宿主内部细节泄漏给扩展。

Hybrid Model

多数成熟系统会混合使用:

  • manifest 声明权限、入口、UI、资源。
  • runtime API 执行业务逻辑。
  • event/hook 触发扩展。
  • store/review 管理发布和安全。

生命周期

阶段关注点
Discover扩展如何被发现:目录、市场、配置扫描、module path
Install安装包格式、签名、依赖、版本约束
Enable启用范围:全局、workspace、tenant、project、user
Activate触发条件:启动时、事件、命令、文件类型、请求阶段
Execute运行时、资源限制、超时、并发、错误隔离
Update版本升级、兼容检查、迁移、回滚
Disable禁用后状态清理、hook 解绑、后台任务停止
Uninstall删除资源、保留用户数据、撤销授权
tip

不要默认让所有扩展在启动时激活。成熟扩展系统通常使用 activation event / lazy loading,避免启动慢、资源浪费和故障放大。

扩展入口设计

入口说明适合
Command用户主动触发命令IDE、设计工具、后台任务
Menu / Toolbar挂载到 UI 操作点Browser、Figma、桌面应用
File Type / UTI针对文件类型自动触发Quick Look、编辑器语言插件
Request Phase请求生命周期中的阶段Nginx、API Gateway、RPC
Event Subscription订阅宿主事件Webhook、automation、workflow
Scheduled Job定时运行同步、清理、报告
Resource Provider注册某类资源 providerStorage、Auth、Payment、LLM provider
UI Contribution注入 panel、view、sidebar、inspectorIDE、Admin console、Design tool

API 契约设计

API 应该稳定在语义层

扩展 API 不应直接暴露内部表、内部对象指针、未稳定的数据结构。推荐暴露:

  • 领域对象:DocumentNodeMessageRequestUser
  • 能力接口:readFilecreateNoderegisterCommandsendMessage
  • 事件:DocumentChangedRequestReceivedCommandExecuted
  • 上下文:workspacetenantselectionrequestContext

常见 API 类型

API 类型说明注意
Query API读取宿主状态控制访问范围和分页
Mutation API修改宿主状态需要权限、事务、审计
Registration API注册命令、菜单、provider、handler要支持注销和冲突处理
Event API订阅事件要有过滤、背压、错误隔离
Storage API扩展私有存储区分 user/workspace/global scope
Secret API管理 token / credential不要把 secret 直接暴露给 UI 或日志
Network API访问外部网络需要域名权限、代理、审计
UI API打开 modal/panel/toast防止钓鱼和权限误导

同步 vs 异步

方式优点风险
Synchronous Hook简单、结果直接影响宿主流程阻塞主流程,扩展慢会拖垮宿主
Async Event解耦、可重试、可隔离最终一致,错误处理复杂
Async Command可等待结果但隔离更好需要 timeout、cancel、progress
Background Task适合长任务需要调度、配额、状态恢复

设计建议:

  • UI 交互可用短同步调用,但必须有 timeout。
  • 请求链路上的扩展尽量非阻塞或明确预算。
  • 长任务使用 async job + progress + cancel。
  • 事件订阅默认不要阻塞生产者。

隔离模型

隔离方式安全性性能例子说明
In-process native最高Nginx C module性能强,但崩溃/内存破坏会影响宿主
In-process script中低Lua plugin、PHP plugin易扩展,但需要限制 API 和资源
Separate processVS Code extension host崩溃可隔离,IPC 有成本
iframe / Web Worker中高Figma plugin UI、browser extension page适合 Web 技术和 UI 隔离
WASM sandboxEnvoy WASMABI 清晰、跨语言,但能力受限
Remote extension低到中Webhook、SaaS integration最强隔离,但网络、延迟、可靠性复杂

权限模型

扩展权限建议采用 least privilege:默认无权限,按能力声明和用户授权。

权限维度例子
Resource文件、页面、项目、租户、请求、消息
Operationread、write、delete、admin、execute
Scopeuser、workspace、project、tenant、global
Network允许访问的 host / domain
Secret可访问哪些 credential、是否只可间接使用
UI是否可弹窗、注入面板、显示通知
Background是否可后台运行、定时运行
Data Export是否可导出数据到外部服务

权限设计要点:

  • 安装时展示权限,运行时敏感操作二次确认。
  • 权限变更需要重新授权。
  • 区分开发模式、本地安装、市场发布版本。
  • 对企业环境支持 allowlist / blocklist / policy。
  • 对扩展访问和数据导出做审计日志。

配置与 Manifest

Manifest 用于描述扩展元数据、入口、权限和贡献点。

{
"id": "example.extension",
"name": "Example Extension",
"version": "1.2.0",
"engines": {
"host": ">=1.0 <2.0"
},
"permissions": ["document:read", "document:write"],
"activationEvents": ["onCommand:example.run"],
"contributes": {
"commands": [
{ "id": "example.run", "title": "Run Example" }
]
}
}

建议字段:

字段说明
id全局唯一扩展 ID
name / description展示信息
version扩展版本,建议 SemVer
engines宿主版本约束
permissions权限声明
activationEvents激活条件
contributes命令、菜单、UI、provider 等贡献点
main / module执行入口
capabilities扩展能力声明
configuration可配置项 schema
dependencies依赖和兼容要求

Hook / Middleware 设计

Hook 类型

类型说明例子
Before Hook主流程执行前,可校验或修改输入beforeSavebeforeRequest
After Hook主流程成功后执行afterCreateafterPublish
Around Hook包裹主流程,可决定是否继续middleware、interceptor
Error Hook主流程失败后执行onError、compensation
Filter Hook输入输出转换WordPress filter、response filter
Observer Hook只观察,不影响主流程audit、metrics、analytics

Middleware 顺序

Middleware 要明确顺序模型:

  • 注册顺序。
  • 优先级 priority
  • phase 分组。
  • 显式 dependency:before / after

常见问题:

  • 多个 middleware 修改同一字段导致冲突。
  • 某个 middleware 未调用 next() 阻断链路。
  • 错误处理 middleware 顺序不清。
  • 同步 middleware 中执行阻塞 IO。

Event 扩展设计

事件适合低耦合扩展,但要注意可靠性和语义。

设计点建议
Event name使用过去式事实,例如 DocumentSaved
Event ID每个事件有唯一 ID,用于幂等
Version事件 schema 要有版本
Filter订阅支持按类型、资源、scope 过滤
Delivery明确 at-most-once / at-least-once
Retry重试要有退避和上限
DLQ失败事件进入死信队列或错误面板
Ordering只承诺必要范围内有序,例如 document 内有序

更多事件驱动设计见 事件驱动

Native Module 设计

Native module 适合高性能或底层能力,但风险最高。

设计要点:

  • ABI/API 版本必须明确。
  • 避免阻塞宿主事件循环或 worker。
  • 明确内存分配和释放模型。
  • 支持 graceful reload / hot restart 时的状态迁移。
  • 崩溃隔离较弱,必须限制加载来源。
  • 对第三方依赖、全局状态、线程安全要格外谨慎。

Nginx 模块是典型例子:模块运行在 worker 进程内,应避免阻塞库、避免随意使用全局变量,内存通常绑定到 request/config/cycle pool。

UI 扩展设计

UI 扩展最容易影响用户信任和产品一致性。

扩展点设计建议
Menu / Command命名清晰,支持快捷键和禁用状态
Sidebar / Panel限制尺寸、生命周期、资源占用
Modal用户主动触发,避免无限弹窗
Inspector / Property Panel与当前 selection/context 绑定
Toast / Notification限频,避免滥用
Custom View明确数据访问边界

安全建议:

  • 扩展 UI 与宿主 UI 有明确边界,避免伪造系统授权界面。
  • 外部内容默认不可信,使用 CSP、sandbox、资源白名单。
  • 敏感操作使用宿主提供的确认 UI,而不是扩展自绘确认框。

数据与状态

扩展通常需要自己的状态存储。

存储范围用途注意
Extension Global扩展全局配置多用户/多租户隔离
User用户偏好跟随账号还是本机要明确
Workspace / Project项目级配置适合团队共享
Document / Resource Metadata绑定到资源的元数据需要迁移和删除策略
Secret Storetoken、API key必须加密和审计
Cache临时数据可清理、不可作为事实源

版本与兼容

扩展生态最难的是长期兼容。

对象策略
Host APISemVer、deprecation period、feature detection
Extension声明兼容的 host version
Manifestmanifest version 独立演进
Event Schema只增不改,消费者忽略未知字段
Permission新权限需要重新授权
Data Schema扩展提供 migration

实践建议:

  • 不要轻易删除 API;先标记 deprecated。
  • 提供 capability detection:host.hasCapability("foo")
  • 提供 polyfill / compatibility layer。
  • 插件市场展示兼容范围和最近更新时间。
  • 宿主升级前可做 extension compatibility scan。

可观测性

扩展系统必须能回答:哪个扩展做了什么、花了多久、失败在哪里。

指标/日志说明
activation count激活次数
execution duration执行耗时
error count扩展错误数
timeout count超时次数
API call count调用宿主 API 次数
permission denied count权限拒绝次数
resource usageCPU、内存、网络、存储
install/update/uninstall audit安装、升级、卸载审计

建议:

  • 错误归因到 extension id / version / command。
  • 给扩展开发者提供日志,但过滤用户敏感数据。
  • 宿主应能禁用高错误率或高资源消耗扩展。
  • 长任务提供 progress、cancel 和 crash recovery。

安全风险

风险说明缓解
权限过大扩展读取/修改不该访问的数据最小权限、scope、审核
数据外传扩展把数据发到外部服务network permission、DLP、审计
Supply Chain扩展更新后变恶意签名、审核、版本锁定、企业 allowlist
Sandbox Escape沙箱逃逸影响宿主进程隔离、WASM、CSP、依赖升级
DoS扩展耗尽 CPU/内存/请求预算quota、timeout、rate limit
UI Spoofing扩展伪造登录/授权界面宿主统一授权 UI、UI 边界
Dependency Risk插件依赖被投毒lockfile、扫描、bundling policy
Native Crashnative 插件崩溃宿主限制 native、隔离进程、审核

设计检查清单

  • 扩展点是否是真实稳定的业务边界,而不是临时内部函数?
  • 扩展是否可以被 lazy activate?
  • 是否有明确权限、scope、审计?
  • 扩展失败是否会拖垮宿主?
  • 是否有 timeout、cancel、retry、DLQ 或错误面板?
  • API 是否隐藏内部实现细节?
  • 扩展数据如何迁移、备份、清理?
  • 是否支持禁用、回滚、版本兼容检查?
  • 是否有开发者工具:日志、调试、schema、类型定义、示例?
  • 是否能在企业环境做 allowlist / blocklist / policy?

常见设计选择

Plugin vs Webhook

维度PluginWebhook
运行位置宿主内或宿主沙箱第三方服务
隔离中到低,取决于沙箱
延迟网络延迟较高
能力可深度集成 UI/API适合集成和通知
风险影响宿主稳定性网络可靠性和认证复杂

Hook vs Event

维度HookEvent
时机主流程中事实发生后
是否影响主流程常常可以通常不应影响
耦合较高较低
错误处理直接影响调用方异步重试/记录
适合校验、拦截、转换通知、同步、自动化

Script vs WASM vs Native

维度ScriptWASMNative
开发门槛
性能最高
安全隔离
跨平台低到中
适合自动化、轻量逻辑网关、策略、高性能沙箱底层、高性能、系统集成

FAQ

扩展点是不是越多越好?

不是。扩展点一旦公开,就会变成长期兼容负担。应该优先开放稳定、高价值、边界清晰的扩展点,而不是把内部生命周期全部暴露出去。

为什么很多插件系统都需要 manifest?

Manifest 让宿主能在执行代码前知道扩展的身份、入口、权限、兼容版本和贡献点,便于审核、安装、权限提示、lazy loading 和兼容检查。

什么时候应该用事件而不是 hook?

如果扩展只是响应一个已经发生的事实,不应该阻塞主流程,用事件更合适。如果扩展必须决定主流程是否继续、修改输入或输出,用 hook/middleware 更合适。

为什么 Figma 这类插件不支持后台常驻?

这是安全、性能和用户体验取舍。用户主动触发、短生命周期的插件更容易控制资源占用,也更容易让用户理解插件正在访问当前文件。

Native plugin 最大的问题是什么?

不是开发复杂,而是隔离弱。native plugin 可以直接影响宿主进程稳定性、安全性和升级兼容,因此一般只适合强审核、高信任或内部场景。

相关