WU / 文档通用微前端
中文

使用 WU 连接服务

发布契约、授权客户端,并完整走通带版本、验证、取消和清理的 RPC 请求。

从客户端到响应

首次集成 RPC 时,请先阅读应用间求和,其中包含 workspace 所需全部文件。本章在此基础上加入契约发现、取消和实验室可运行服务。

在服务与 RPC中,两个 WU 应用使用不同权限协作。提供方发布服务并响应通道,客户端消费契约并请求响应。流程可测试有效数据、错误、版本不兼容、取消和提供方移除。

Cliente WU
  → consume('docs:backend:service', '^1.0.0')
  → request('docs:backend:request', solicitud)
  → handler del proveedor WU
  → respuesta { status, headers, body, execution }

请求通过运行时内部的 WU RPC 传递。status、headers 和 body 是响应契约成员,不代表门户打开了 HTTP 连接或服务器端口。

申请并授予所需权限

每个 manifest 声明应用申请的能力。提供方需要 rpc.provide:docs:backend:*,客户端需要 rpc.call:docs:backend:*。shell 初始化两个应用时授予这些 scopes:

await wu.init({
  sandbox: 'module',
  apps: [
    {
      name: 'backend-service',
      url: '/microfrontends/backend-service',
      grants: ['rpc.provide:docs:backend:*'],
    },
    {
      name: 'backend-client',
      url: '/microfrontends/backend-client',
      grants: ['rpc.call:docs:backend:*'],
    },
  ],
});

manifest requests 与 shell grants 必须匹配,实际权限来自两者交集。应用使用 mount 收到的 scoped facade context.wu,无需捕获宿主特权 singleton。权限参考进一步解释 scopes 和撤销。

发布通道与契约

提供方挂载过程中,appWu 是 scoped facade,handleRequest 实现服务:

const release = appWu.handle(
  'docs:backend:request',
  handleRequest,
  { version: '1.0.0', allow: ['backend-client'] },
);

const contract = appWu.provide(
  'docs:backend:service',
  { channel: 'docs:backend:request', method: 'POST' },
  {
    version: '1.0.0',
    shape: { channel: 'string', method: 'string' },
  },
);

handle 注册通道响应方,provide 发布消费方发现服务所需的数据。处理函数 allowlist 将请求方限制为 backend-client,拥有 grant 也不能跳过这项额外检查。shape 检查契约成员及其类型,请求体验证则属于服务。

在 WU Framework 4.0.0 中,wu.handle(channel, handler, options) 和 wu.eventBus.handle(channel, handler, options) 均保留版本和允许列表。微应用内部应使用 context.wu.handle:除这些选项外,它还应用该应用的身份和授权。请参阅版本页面以确认实验室的运行时。

通过 provide 发布的名称属于首个提供者。其他应用或试图替换它的宿主会收到 WU_CAPABILITY_OWNED,直到所有者调用 revoke 或通过 unmount 卸载。契约版本不能绕过这种所有权。

从客户端消费并调用

客户端获取契约 proxy,并申请兼容范围。访问 api.channel 时会解析可用提供方并检查范围:

const api = appWu.consume('docs:backend:service', '^1.0.0');
const channel = api.channel;
const controller = new AbortController();

const pending = appWu.request(channel, {
  method: api.method,
  path: '/validate',
  body: JSON.stringify({ name: 'catalog', entry: 'entry.js' }),
}, {
  version: '^1.0.0',
  timeout: 3500,
  signal: controller.signal,
});

const response = await pending;
console.log(response.status, response.body);

兼容性检查有两层:消费契约和 RPC handler。版本不兼容场景向 1.0.0 契约请求 ^2.0.0,在解析阶段失败,服务尚未开始工作。提供方被移除后也不能处理新请求。签名和错误请参阅事件、RPC 与契约。

区分响应与拒绝

服务要求 POST、已知路径,以及不超过 4096 UTF-8 字节的字符串请求体。

请求 服务响应
/validate 使用有效 JSON,并包含 name/entry 200,带 ok: true
/validate 的 manifest 不满足这些规则 422,带验证错误
/uppercase 200,返回转换为大写的 ASCII 文本
/failure 500,表示受控服务失败
/slow,不取消 工作超过 2500 ms 限制时返回 504
未知路由 404,不启动工作
非 POST 方法 405
无效请求结构 400
请求体超出限制 413

这些响应把 RPC Promise 解析为对象,客户端必须检查 response.status。契约不兼容、提供方缺失或取消则作为拒绝,通过 try/catch 处理。

manifest 示例仅验证 name 和 entry。结果声明 scope: "name+entry" 和 completeValidation: false,不检查完整 manifest、权限、发布路由或 entry 存在性。继续诊断项目请参阅配置与 manifests和 WU doctor。

取消和卸载后不保留活动工作

请求仍在等待时,客户端可以执行:

controller.abort();

处理函数接收包含 signal 的 RPC 上下文。本示例中,提供方将信号连接到执行器中断。忽略 signal 的处理函数可能在客户端停止等待后继续工作。

3500 ms RPC 时限和 2500 ms 工作限制作用不同:前者限制 WU 等待,后者允许服务终止工作并响应 504。界面提供慢速示例,可在两项时限之前观察取消。

提供方卸载时,实现会停止活动请求并移除发布内容:

backend.dispose();
release();
contract.revoke();

WU 也撤销应用关联权限。重新挂载时注册新的 handler 和契约。每个请求在完成、失败或取消时释放 abort 监听器、timer 和执行器。生命周期指南解释如何将资源所有权绑定到 mount 与 unmount。

阅读并验证示例

提供方源码展示请求处理和清理。在门户仓库运行检查:

npm ci
npm run build
npm run dev:shell
# En otra terminal:
npm run test:backend

测试覆盖响应、版本不兼容、撤销、重新挂载、超时、取消及请求期间卸载,也检查结束后没有保留 Worker,且流程没有页面错误。

示例实现

提供方在 Worker 中执行项目包含的已编译 WASI 程序,因此能处理真实数据并从浏览器停止工作。宿主和虚拟文件属于服务实现;本章学习的公开契约是 WU,框架不包含通用 WASI 引擎。

可以将实现替换为应用的已授权服务,保持兼容契约,并测试响应、错误和清理。远程服务必须重新验证身份、权限和数据。Node 页面渲染或外部 MCP 客户端连接仍需要对应进程和传输,请参阅 SSR和 AI/MCP。

一起完善 WU

发现了问题?有新的想法?

你的使用体验能让 WU 变得更好。告诉我们遇到的问题,或支持项目的持续开发。