使用 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。