Fronts 2.0
运行时指南

解析与交付

部署解析、策略上下文、缓存、预加载、不可变发布、回滚,以及 transport 所有权。

策略与加载必须分离

逻辑引用不应随着 CDN 搬迁、版本提升、tenant override 或 bundler 更换而变化:

const ref = {
  name: 'checkout',
  expose: './application',
  range: '^2.4.0',
  channel: 'stable',
};
const context = {
  environment: 'production',
  tenant: 'acme',
  cohort: 'experiment-b',
};

resolver 将两者变成一个具体、不可变结果,例如版本 2.4.3、唯一 remote 名称、版本化 mf-manifest.json 和 deployment ID。loader 不重新运行任何业务策略,只执行已经解析的 source。

Resolver 组合与 registry

Fronts 提供 createStaticResolver()(测试、本地与确定性 fallback)、createRegistryResolver() (HTTP registry)、带 fresh/stale 窗口的 createCachedResolver()、顺序 fallback resolver 和可插拔 ResolutionCache/内存实现。默认 cache key 包含 name、expose、range、channel、environment、tenant 与 cohort;若自定义 metadata 参与版本选择,必须提供自定义 key,否则不同策略上下文可能误用同一决策。

内置 registry resolver 通过 GET 发送存在的 name, expose, range, channel, environment, tenant, cohort。最小响应包含 source,还可包含 versionmetadata。认证 header、credential、endpoint 计算、fetch 与 payload decoding 均可注入。服务端必须认证 caller 并验证所有 policy input,浏览器 query 绝不能证明 tenant/cohort 成员身份。

基于解析结果规划容器

registry 返回具体部署后,mount 才能从 metadata 决定执行边界;planner 在同一 transaction 内、 container-specific loader 选择之前运行:

container: ({ identity, resolved }) => {
  const frame = resolved.metadata?.frame;
  if (typeof frame !== 'object' || frame === null) return { type: 'dom' };
  const url = Reflect.get(frame, 'url');
  const origin = Reflect.get(frame, 'origin');
  if (typeof url !== 'string' || typeof origin !== 'string') {
    throw new Error('Invalid iframe deployment metadata.');
  }
  return { type: 'iframe', src: url, targetOrigin: origin, title: identity.name };
};

在构造 request 前必须校验外部 metadata。Fronts 会快照 request,通过 containerLoaders 选择 loader,并把同一份冻结 ResolvedApp 交给 prepare context,避免计划与执行使用不同决策。

Module Federation source 规则

@fronts/mf 接受官方 Remote 形状的 entry-based 或 version-based remote。它在调用者提供的 MF instance 上注册具体 remote,根据 source 和规范化 ref 生成 remoteName/expose,调用 loadRemote(id, { from: 'runtime' }),把 null/异常映射为 Fronts load error,并在 preload 时调用 preloadRemote()。同一 instance 内,已观察到的 remote name 若绑定到不同 source 或已知版本会被 拒绝,除非调用者明确 force replacement。

优先 manifest,而不是裸 remote entry,因为 manifest 保留官方预加载、snapshot、类型提示和 DevTools 所需的资源及 shared metadata。Fronts 把这些内容当作 MF-owned opaque data,绝不修改 全局 snapshot。

版本、channel 与缓存策略

registry 应只用不可变已发布版本满足 semantic range;在服务端把 stable/canary/next channel 映射 到具体 deployment;以已认证 subject + experiment salt 确定 cohort;返回具体版本、不可变 URL 和 policy revision/deployment ID;在同一 MF instance 中不要复用 mutable remote name;至少在回滚窗口 内保留旧 artifact。Fronts 不规定 registry 数据库或 rollout 算法,这些属于独立可运维的 deployment plane。

缓存 fresh TTL 内直接返回;fresh 过期后 refresh 失败,才可在有限 stale TTL 内返回旧解析。它是 可用性行为,不是静默版本 fallback。每次使用 stale 都应发 telemetry,artifact 必须仍不可变可用, 且安全撤销不能被长 stale window 绕过;敏感应用需要 kill-switch 或极短 TTL。

预加载、安全发布与回滚

host.preload() 解析相同策略并请求 transport preload,不挂载、不创建 service scope,也不占用 container。MF preload promise 汇总资源成败;除非产品在导航前必须取得应用,否则 rejection 应视为 优化失败,而不是运行时已经不可用。

安全发布使用不可变 URL + Fronts replacement:registry 向目标 cohort 推广 B;Host 解析 B 并在 staging slot 挂载;B 通过协议和 readiness 后才 commit 并卸载 A;若 staging 失败,A 继续活跃; registry 可降级 B,使后续解析返回 A 或修复后的 C。常规 rollout 不要对已活跃 remote 调 registerRemotes(..., { force: true }),因为官方 Runtime 会清理 loaded-module cache;唯一 remote name 配合应用级 replace 更容易审计。

非目标与验证

Fronts 不发布 artifact、不签名 manifest、不生成类型、不运营 registry,也不选择 shared 版本。 core resolver/host 测试验证规范化、policy snapshot、缓存窗口、取消、preload 与 resolved decision; MF adapter 测试证明只调用官方公开注册、预加载和加载 API;replacement 测试证明 promotion/rollback。

本页目录