Hooks、Middleware、Plugins的区别及应用场景

5 阅读5分钟

最近在看 Claude Agent SDK, 里面特别提到了 Hooks,有各种各样的 Hooks, 例如 PreToolUse(工具调用前执行)、PostToolUse(工具调用后执行)、PostToolUseFailure(工具失败时执行)..., 于是联想到 Middleware 和 React Hooks, 总结下几个概念的差异。

下面我把 hooks / middleware / plugin 当作三种“可扩展点(extension points)”来对比:它们解决的都是“如何让外部代码参与到系统的某个过程里”,但参与方式、控制权、适用问题域不一样。


1) Hooks:在“时间点”上挂回调(事件/生命周期)

核心模型:系统在特定时刻(before/after/onX)发出信号,你注册的回调被调用。
更像“发布订阅 / 生命周期事件”。

优势

  • 简单直观:只要定义“什么时候会触发”,外部就能插一段逻辑。
  • 侵入性低:不要求你理解整个流程,只需关注那个点。
  • 组合灵活:很多 hook 可以并存(多个监听者),便于做埋点、日志、统计、校验等“附加行为”。

劣势(常见坑)

  • 控制流分散:逻辑被拆到很多回调里,调试和追踪调用链更难。
  • 顺序与冲突:多个 hook 谁先谁后?是否允许“短路/阻止默认行为”?一旦规则不清就会乱。
  • 语义容易漂移:hook 名叫 beforeSave,到底能不能改数据、能不能抛错终止、能不能异步?如果约定不严,很快变成“随便用”。

典型应用场景

  • 生命周期:组件 mount/unmount、任务开始/结束、事务提交前后。
  • 旁路逻辑:日志、metrics、A/B 实验、审计、权限校验、预加载、缓存刷新。
  • 可选增强:比如校验规则扩展、数据转换、字段补全。

直觉:当你想给系统加“在某些时刻顺便做点事”,hooks 很合适。


2) Middleware:在“请求/处理链路”上做管道(pipeline)

核心模型:有一个明确的链式流程 req -> mw1 -> mw2 -> ... -> handler -> ... -> response
每个 middleware 通常拿到上下文 + next(),可以:

  • 在调用 next() 前后包一层(环绕)
  • 修改上下文(请求、响应、状态)
  • 决定是否继续(短路)

优势

  • 控制流清晰:就是一条链(尤其对请求/命令/事件处理这类流程),可预测性强。
  • 适合横切关注点:鉴权、限流、日志、压缩、异常处理、Tracing(典型 web 框架)。
  • 天然支持“环绕” :比如计时:start -> next -> end;异常捕获也是“包一层”。

劣势

  • 强约束:要求你的问题能抽象成“管道式处理”,否则会硬套得别扭。
  • 顺序高度敏感:鉴权在限流前后、body parse 在路由前后都会影响行为。
  • 容易滥用为“全能拦截器” :链太长就像洋葱,理解成本上升。

典型应用场景

  • HTTP/RPC 请求处理、消息消费处理、命令执行链、事件分发链
  • 横切能力标准化:auth、rate-limit、cache、retry、timeout、idempotency、observability

直觉:当你有一条“必经之路”的处理链,并且需要在链上做环绕/拦截,middleware 是最稳的。


3) Plugins:在“能力/模块”层面做扩展(装配/功能注入)

核心模型:插件是更粗粒度的扩展单元,往往包含:

  • 新的功能模块(命令、页面、协议、数据源、规则引擎)
  • 与宿主的一套契约(API/SDK/manifest)
  • 可能还会注册 hooks / middlewares(插件内部使用它们)

优势

  • 扩展能力最强:不仅是加一段逻辑,而是加一整个“功能包”。
  • 隔离与版本化:可以独立发布、启停、升级、授权、沙箱隔离(做得好的话)。
  • 生态友好:适合第三方开发者、市场化分发(IDE、CMS、浏览器、平台型产品)。

劣势

  • 架构成本最高:要设计插件生命周期、依赖管理、权限/安全、兼容性、沙箱、配置等。
  • 治理复杂:插件之间冲突、性能、稳定性、可观测性、升级策略都要管。
  • API 一旦发布难以收回:对外契约会变成长期负担。

典型应用场景

  • 平台化产品:IDE(扩展)、浏览器(扩展)、CMS(插件)、数据平台连接器、工作流平台
  • 多团队/第三方共建:需要“独立交付、独立治理”的扩展方式

直觉:当你要让别人“带着一整个功能来接入”,而不是“在流程里插一段”,就该上 plugin。


横向对比:一句话抓差异

  • Hooks:我在 某个时刻 通知你,你来做点事。(点状扩展)
  • Middleware:你在 必经流程 上一层层包起来,能拦截能短路。(链路扩展)
  • Plugin:你以 模块/产品能力 的形态接入,可能内部再用 hook/mw。(能力扩展)

选择建议(经验法则)

用 Hooks 的时候

  • 需求是“在 X 之前/之后补充逻辑”
  • 不想改变主流程,只想附加行为
  • 回调之间最好 无强依赖(否则顺序治理会很痛)

用 Middleware 的时候

  • 明确存在一条处理链(请求、任务、消息、命令)
  • 你需要 环绕(前后包裹)、短路、统一错误处理、统一上下文改写

用 Plugin 的时候

  • 你要交付的是“一个功能模块”,而不是一个回调
  • 需要独立版本、启停、配置、权限、安全隔离
  • 你希望形成生态(内部多团队/外部开发者)

实践中的常见组合(很推荐)

很多成熟系统会分层设计:

  • Plugin(模块级) :负责装配能力、注册扩展点
  • Middleware(链路级) :统一处理通用横切能力
  • Hooks(点状) :细粒度生命周期与事件

这样既能平台化,又不会把所有东西都塞进 hook 或 middleware 导致治理失控。