@fulgurjs/federation 5.9.3 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.en.md +57 -416
  3. package/README.md +56 -446
  4. package/dist/bridge-app-vue.d.cts +1 -1
  5. package/dist/bridge-app-vue.d.ts +1 -1
  6. package/dist/bridge-core.cjs +1 -1
  7. package/dist/bridge-core.js +2 -2
  8. package/dist/bridge-errors.cjs +1 -1
  9. package/dist/bridge-errors.js +1 -1
  10. package/dist/bridge-host-react.cjs +1 -1
  11. package/dist/bridge-host-react.js +3 -3
  12. package/dist/bridge-host-vue.cjs +1 -1
  13. package/dist/bridge-host-vue.js +3 -3
  14. package/dist/bridge-router-react.d.ts +4 -2
  15. package/dist/bridge-router-react.js +95 -9
  16. package/dist/bridge-router-vue.d.ts +24 -5
  17. package/dist/bridge-router-vue.js +4 -5
  18. package/dist/{chunk-YKIFZIBH.js → chunk-77JZ6U6V.js} +1 -1
  19. package/dist/{chunk-Q6V5O5Y6.js → chunk-ENT3BOTX.js} +1 -1
  20. package/dist/{chunk-WRJG2YG6.js → chunk-ZAYNS7YQ.js} +1 -1
  21. package/dist/cli.js +460 -109
  22. package/dist/index.cjs +25 -38
  23. package/dist/index.js +25 -38
  24. package/dist/react.d.ts +194 -101
  25. package/dist/react.js +4 -0
  26. package/dist/runtime-entry.d.ts +9 -174
  27. package/dist/runtime-entry.js +0 -1
  28. package/dist/runtime.js +1 -1
  29. package/dist/vue.d.ts +576 -0
  30. package/dist/vue.js +8 -0
  31. package/docs/en/migration.md +210 -0
  32. package/docs/en/reference/api.md +534 -0
  33. package/docs/en/reference/errors.md +86 -0
  34. package/docs/{P5-vite7-8 → maintainers/P5-vite7-8}/345/205/274/345/256/271/347/237/251/351/230/265.md +7 -9
  35. package/docs/{webpack-mf- → maintainers/webpack-mf-}/345/257/271/347/205/247/344/270/216/347/274/272/345/217/243.md +10 -10
  36. package/docs/maintainers//346/262/231/347/256/261/350/276/271/347/225/214/345/256/241/350/256/241.md +43 -0
  37. package/docs/zh/migration.md +210 -0
  38. package/docs/zh/reference/api.md +533 -0
  39. package/docs/zh/reference/errors.md +86 -0
  40. package/examples/templates/README.md +1 -1
  41. package/examples/templates/react-host-vue-remote/pnpm-workspace.yaml +1 -1
  42. package/examples/templates/react-host-vue-remote/react-host/README.md +2 -2
  43. package/examples/templates/react-host-vue-remote/react-host/package.json +1 -1
  44. package/examples/templates/react-host-vue-remote/react-host/src/main.tsx +2 -2
  45. package/examples/templates/react-host-vue-remote/scripts/dev.config.json +11 -2
  46. package/examples/templates/react-host-vue-remote/vue-remote/package.json +1 -1
  47. package/examples/templates/react-host-vue-remote/vue-remote/src/bridge.ts +1 -1
  48. package/examples/templates/react-react/host/package.json +1 -1
  49. package/examples/templates/react-react/pnpm-workspace.yaml +1 -1
  50. package/examples/templates/react-react/remote/package.json +1 -1
  51. package/examples/templates/react-react/scripts/dev.config.json +11 -2
  52. package/examples/templates/showcase/README.md +6 -6
  53. package/examples/templates/showcase/pnpm-workspace.yaml +1 -1
  54. package/examples/templates/showcase/react-host/package.json +1 -1
  55. package/examples/templates/showcase/react-host/src/pages/BridgeVuePage.tsx +1 -1
  56. package/examples/templates/showcase/react-host/src/routing.ts +1 -1
  57. package/examples/templates/showcase/react-remote/package.json +1 -1
  58. package/examples/templates/showcase/react-remote/src/bridge.tsx +1 -1
  59. package/examples/templates/showcase/scripts/dev.config.json +22 -4
  60. package/examples/templates/showcase/vue-host/package.json +1 -1
  61. package/examples/templates/showcase/vue-host/src/pages/BridgeReactPage.vue +1 -1
  62. package/examples/templates/showcase/vue-host/src/routing.ts +3 -13
  63. package/examples/templates/showcase/vue-remote/package.json +1 -1
  64. package/examples/templates/showcase/vue-remote/src/bridge.ts +2 -2
  65. package/examples/templates/vue-host-react-remote/pnpm-workspace.yaml +1 -1
  66. package/examples/templates/vue-host-react-remote/react-remote/package.json +1 -1
  67. package/examples/templates/vue-host-react-remote/scripts/dev.config.json +11 -2
  68. package/examples/templates/vue-host-react-remote/vue-host/README.md +2 -2
  69. package/examples/templates/vue-host-react-remote/vue-host/package.json +1 -1
  70. package/examples/templates/vue-host-react-remote/vue-host/src/App.vue +2 -2
  71. package/examples/templates/vue-vue/host/package.json +1 -1
  72. package/examples/templates/vue-vue/host/src/main.ts +28 -21
  73. package/examples/templates/vue-vue/host/src/pages/HomePage.vue +1 -1
  74. package/examples/templates/vue-vue/pnpm-workspace.yaml +1 -1
  75. package/examples/templates/vue-vue/remote/package.json +1 -1
  76. package/examples/templates/vue-vue/scripts/dev.config.json +11 -2
  77. package/package.json +24 -37
  78. package/dist/bridge-core-D37VanBl.d.ts +0 -99
  79. package/dist/bridge-host-react-CGymCzD2.d.ts +0 -35
  80. package/dist/bridge-host-vue-B3GHaQAC.d.ts +0 -32
  81. package/dist/bridge-react.d.ts +0 -14
  82. package/dist/bridge-react.js +0 -3
  83. package/dist/bridge-vue.d.ts +0 -8
  84. package/dist/bridge-vue.js +0 -3
  85. package/dist/bridge.d.ts +0 -18
  86. package/dist/bridge.js +0 -5
  87. package/dist/chunk-GLASM5EX.js +0 -1730
  88. package/dist/chunk-V6EASSCR.js +0 -249
  89. package/dist/chunk-X34EJB4H.js +0 -207
  90. package/docs/API.en.md +0 -339
  91. package/docs/API.md +0 -914
  92. package/docs//346/262/231/347/256/261/350/276/271/347/225/214/345/256/241/350/256/241.md +0 -45
  93. package/docs//350/277/201/347/247/273/346/214/207/345/215/227.md +0 -179
@@ -0,0 +1,86 @@
1
+ # 错误码总表
2
+
3
+ > 48 个错误码,按段分组:CFG(配置期)/ DEV(开发期)/ BLD(构建期)/ MFU(运行时)/ CC(跨应用上下文)。每条给出**现象 / 原因 / 修法**三段式。错误文案中的修法具体到配置键 / 文件 / 命令;`fulgurjs doctor` 可提前把部署面的 MFU-001 类问题拦在上线前。
4
+ >
5
+ > 维护提示:新增/修改错误码必须三处同步——源码码表(`src/runtime/errors.ts` 的 MFU 段 / `src/context.ts` 的 CC 段)+ 登记表 `CODE_REGISTRY`(`src/diagnostics.ts`)+ 本表;`npm run build` 里的 `scripts/check-manual-codes.mjs` 做三方一致性校验(见[维护者 · 测试方法](../../maintainers/testing.md))。
6
+
7
+ ### 6. 错误码总表
8
+
9
+ #### CFG 配置期
10
+
11
+ | 码 | 现象 | 原因 | 修法 |
12
+ |---|---|---|---|
13
+ | `CFG-001` | vite config 阶段报「缺少必填的 name」或「name 格式不正确」 | `federation({})` 缺 name,或 name 不匹配 `/^[a-zA-Z][\w.-]*$/`(空串/数字开头/含空格斜杠) | 在 `federation({ name: 'my-app' })` 声明同一页面内唯一的非空字符串 |
14
+ | `CFG-002` | 配置期报「exposes 必须是对象」或 `exposes["x"].import 缺失` | exposes 写成了数组/字符串,或某条目缺少源文件路径 | 写成形如 `{ './Module': './src/path' }` 的对象;每键值是路径字符串或 `{ import: './src/path' }` |
15
+ | `CFG-003` | 配置期报「remotes 键包含非法字符」/「没有地址」 | remotes 键含 `@`、`/` 或空白;或某远程未填任何地址 | 键用纯模块名(如 `remote-a`,同时是 import 前缀);`external`/`dev`/`prod` 至少填一个地址 |
16
+ | `CFG-004` | 配置期报「shared 必须是数组或对象」 | shared 写成了字符串等非法形态 | 用 `['vue']` 或 `{ vue: { singleton: true } }` |
17
+ | `CFG-005` | 配置期报 remotes 键与 shared 键同名冲突 | 同一个名字既在 `remotes` 又在 `shared`——加载改写规则会互相覆盖 | 重命名其一(通常改 remotes 键,如 `vue` → 不允许则用别的前缀名) |
18
+ | `CFG-006` | 启动时警告「未配置 exposes 或 remotes,目前只会注册共享依赖」 | 孤岛配置:既不提供也不消费(常见于手滑删了 exposes) | 要提供模块配 `exposes`;要消费远程配 `remotes` |
19
+ | `CFG-007` | 配置期报「对象写法不支持 name@ 前缀」 | `remotes['x'].dev/prod` 写成 `'bpm@http://…'`——对象形式整串当 URL 拼接,产出坏地址(运行时表现为无关的 MFU-001) | 对象 dev/prod 槽位写不带前缀的 URL(远程名称默认用键名);需要改名用字符串写法 `'name@url'` |
20
+ | `CFG-008` | 配置期报「不能同时配置 eager 和 import:false」或「共享键重复声明」 | `eager` 需要本地副本打进初始 chunk,与 `import: false`(纯消费)互斥;或同 shareKey+shareScope 声明了两次 | 二选一:`{ eager: true }` 或 `{ import: false }`;合并重复声明或改用不同 shareKey |
21
+ | `CFG-009` | 配置期报 timeout/retries/breaker 数值非法 | `timeout`/`breaker.threshold`/`breaker.resetMs` 非有限正数;`retries` 非 0–10 整数 | `timeout: 15000`、`retries: 2`(上限 10 防退避风暴)、`breaker: { threshold: 5, resetMs: 30000 }` |
22
+ | `CFG-010` | 配置期报 devCorsOrigins 形态非法 | 值既不是 `"*"` 也不是 http(s) 来源数组 | `'*'`(全放开)或 `['http://localhost:5100', …]` allowlist |
23
+ | `CFG-011` | 配置期报「选项 xxx 已在 5.0.0 删除」并给迁移写法 | 传入了 webpack 兼容/无效选项:`remoteType`/`library`/`automaticAsyncBoundary`/`dataPrefetch`/`usedExports`/`ignoreUnusedSharedExports`(任何值含历史合法值都报) | 直接删除该字段:remoteEntry 恒为 ESM、TLA 异步边界恒开、tree-shaking 由打包器原生完成;预载用运行时 `preloadRemote()`(`/runtime` 导出) |
24
+ | `CFG-012` | 配置期报「setup 必须是相对应用根目录的非空模块路径」或「exposes 键已由联邦 setup 入口保留」 | setup 为空/非字符串;或 exposes 占用内部保留键 `./__fulgurjs_setup__` | setup 写如 `'./src/fulgurjs/setup.ts'`;保留键改名为其他公开 expose,原文件路径配置到 `federation({ setup })` |
25
+
26
+ #### DEV 开发期
27
+
28
+ | 码 | 现象 | 原因 | 修法 |
29
+ |---|---|---|---|
30
+ | `DEV-001` | dev 启动/首次加载报远程 manifest 拉取失败 | remote dev server 不可达(未启动/端口错/网络) | 确认远程 dev server 已启动且 `remotes[*].dev` 地址正确;`npx fulgurjs doctor --base http://localhost:<端口> --apps <子目录> --dev` 体检 |
31
+ | `DEV-002` | dev 提示 remote manifest 为空或格式不识别 | 对端不是 fulgurjs 插件产物,或插件版本过旧 manifest 形状不识别 | 对端安装/升级 @fulgurjs/federation 并重启其 dev server;核对访问的是 `@fulgurjs-manifest.json` 端点 |
32
+ | `DEV-004` | dev 预构建警告:已知 UMD-only 依赖不在 optimizeDeps.include | UMD/CJS 依赖被移出预构建,存在预构建内联本地 vue 风险 | 把该依赖放回 `optimizeDeps.include`(插件自动外部化 shared 键) |
33
+ | `DEV-005` | dev 提示 remotes dev URL 端口无监听 | `remotes[*].dev` 指向的端口没有进程监听(远程未启动或改了端口未同步) | 启动远程 dev server;按[改端口四处清单](../guide/examples.md#改端口的固定清单)同步宿主 remotes dev 地址 |
34
+ | `DEV-006` | dev 启动警告宿主/远程插件版本不一致 | 同页面多个应用的 @fulgurjs/federation 版本不同(运行时副本风险) | 统一各应用插件版本(workspace 内对齐依赖;独立仓库用相同版本号) |
35
+ | `DEV-009` | dev 页面报门面/虚拟模块 404 | `.vite` 缓存漂移(插件升级后旧缓存与新门面签名不匹配) | `rm -rf node_modules/.vite` + 重启 dev server(必要时换浏览器 profile) |
36
+ | `DEV-010` | dev 冷启动首轮 30~60s 出现瞬时 504/"ce" 或页面重载 | Vite 依赖预构建窗口(新依赖发现触发重新优化 + full reload),是瞬态不是故障 | 先真实打开页面预热再做断言/测试;稳定态不受影响 |
37
+ | `DEV-011` | dev 启动提醒:非 loopback host + 通配 dev CORS | `devCorsOrigins` 缺省/`'*'` 且 host 暴露到局域网,联邦端点对任意来源放开 | 显式 `devCorsOrigins: '*'`(声明知情)或改来源 allowlist 数组 |
38
+ | `DEV-012` | dev 启动提醒:非 loopback host + dev manifest 携带 fsRoot | dev manifest 含本机绝对路径(`fsRoot`),非 loopback 访问时本机路径外发 | `devFsRoot: false`(宿主 dts 降级 any 桩并提示);`fsRoot` 永不进入 prod manifest |
39
+
40
+ #### BLD 构建期
41
+
42
+ | 码 | 现象 | 原因 | 修法 |
43
+ |---|---|---|---|
44
+ | `BLD-001` | 构建报 expose 源文件解析失败 | `exposes` 值指向的文件不存在/语法错误/路径指向项目外 | 核对 exposes 的源文件路径(相对项目根);修复文件或路径 |
45
+ | `BLD-002` | 构建报构建目标低于 es2022 | `build.target` 低于 es2022——顶层 await(TLA)需要 | `build.target: 'es2022'` 或更新 |
46
+ | `BLD-003` | 构建警告 expose 目标组件含必填 props | expose 的组件声明了无默认值的必填 props——宿主按 props 透传时可能渲染缺参 | 必填 props 给默认值,或在使用处保证始终传入 |
47
+ | `BLD-006` | 构建报 output 数组形态下无法自动注入协商门面 chunk 隔离 | `build.rollupOptions.output` 是数组,插件无法自动加协商门面 chunk 隔离分支 | 手工在 output 各分支补齐插件提示的隔离规则 |
48
+
49
+ #### MFU 运行时
50
+
51
+ | 码 | 现象 | 原因 | 修法 |
52
+ |---|---|---|---|
53
+ | `MFU-001` | 运行时报远程容器/模块加载失败(含网络/超时/重试耗尽/熔断) | 远程不可达、入口地址错、超时后重试耗尽、或连续失败触发熔断 | 核对 remote 地址与可用性;配置 `fallback` 备用入口或调 `timeout`/`retries`;上线前用 `fulgurjs doctor` 体检部署面 |
54
+ | `MFU-002` | 运行时报 remoteEntry 自报名与配置名不一致 | 容器自报的 name 与 `remotes` 键/配置期望不一致(重命名未对齐) | 改 remotes 键对齐自报名,或用字符串 `'自报名@url'` 写法显式声明重命名 |
55
+ | `MFU-003` | 运行时抛 strictVersion 版本不满足 | `strictVersion: true`(或缺省规则命中)且协商到的版本不满足 `requiredVersion` | 对齐各应用依赖版本;或放宽 strictVersion/requiredVersion(确认兼容后) |
56
+ | `MFU-004` | 运行时报共享模块缺失且无本地 fallback | 请求的 shared 键没有任何提供方,且本应用未提供本地副本(`import: false`);或未准备的同步消费者遇到异步 resolveShare hook(`details.syncUnsupported: true`) | 确认提供方 shared 声明与本端加载顺序;自定义入口先 `await loadShare(name, opts)` 再动态导入新消费者 |
57
+ | `MFU-005` | 运行时报同一容器用不同 share scope 重复 init | 同一容器被以两个不同 shareScope 初始化(协商状态歧义) | 统一该远程的 shareScope(remotes 配置与运行时注册保持一致) |
58
+ | `MFU-006` | 运行时报请求的模块未被该远程 exposes | spec 的 expose 键与远程 exposes 清单对不上 | 核对 `远程名/exposes 键`(spec 不要重复加远程名前缀;`fulgurjs check-pages` 可批量核对) |
59
+ | `MFU-007` | console 警告预加载失败(不阻断业务) | `preloadRemote` 预取的 chunk/CSS 不可达 | 查 `fulgurjs:error` 事件历史与远程部署;预载失败不影响后续真实加载 |
60
+ | `MFU-008` | 运行时报未知远程 | spec/调用里的远程名不在 `remotes`/运行时注册表里 | 核对远程名拼写;动态远程先 `registerRemote`/`registerRemotes` |
61
+ | `MFU-009` | 运行时报加载到的模块没有任何导出 | expose 目标文件没有导出(空模块/只有副作用) | 给 expose 目标文件补导出;确认加载的是预期文件 |
62
+ | `MFU-010` | 运行时警告选中的共享单例版本不满足某消费方要求(列出候选版本、提供方、影响与修法;同一组合只告警一次) | singleton 收敛到的版本不在某消费方 requiredVersion 内;或桥接宿主/子应用缺 singleton 导致双实例症状(Invalid hook call) | 统一依赖版本;确认告警可接受或调整 requiredVersion;跨框架宿主三键 singleton |
63
+ | `MFU-011` | 运行时报 setup 生命周期入口导出形态非法(报实际类型/预期签名/修法) | setup 模块的默认导出或具名 `onSession` 不是函数(其他导出不作为入口) | setup 文件默认导出 `setup(context)` 函数;可选具名导出 `onSession(context)` 函数 |
64
+ | `MFU-012` | 该次 `loadRemote` 拒绝,报 setup/onSession 执行抛错(cause 含原始异常) | 初始化代码自身抛错 | 修复 setup/onSession 内部错误后直接重试——只清失败阶段缓存(setup 失败重试从 setup 开始;onSession 失败只重跑会话段),已成功阶段不重复 |
65
+ | `MFU-013` | 运行时报远程声明 onSession 但宿主 AppContext 缺 sessionKey | 宿主未提供非敏感登录代次 ID(禁止用 token 充当) | 宿主登录流程 `provideAppContext({ sessionKey })`——每次成功登录/重登生成新值,token 刷新沿用 |
66
+ | `MFU-014` | 运行时报 setup/onSession 同步段内递归 loadRemote 同一远程 | 初始化同步段内加载同远程模块——该调用会等待自身形成死锁 | 初始化内不要加载同远程模块;跨远程加载放异步段 |
67
+ | `MFU-015` | 运行时报桥接契约非法(`./bridge` 默认导出缺 mount/unmount 或非函数) | expose `./bridge` 的模块没有用 `defineBridgeApp` 构造契约对象 | 子应用入口改用 `defineBridgeApp(...)` 默认导出(见[子应用桥接](../guide/app-bridge.md)) |
68
+ | `MFU-016` | 运行时报桥接准备或生命周期失败(`details.phase` 区分 getContext/mount/unmount;根因含子应用原始错误) | getContext 返回 Promise/非对象、mount 首次提交前抛错、或 unmount 清理抛错 | 按 phase 排查子应用代码:getContext 返回同步快照对象;mount 失败先清理 app/root 再抛;unmount 修复清理逻辑——unmount 抛错的容器被持久封锁,整页刷新恢复 |
69
+ | `MFU-017` | 运行时报桥接会话参数与 AppContext 不一致 | 受控 `sessionKey` 与全局会话矛盾(getContext 快照不一致)、非法值(空串/数字)、或页面级单会话冲突(多实例代次不一致) | 同页受控桥接实例统一会话;sessionKey 只用 非空字符串/null/省略 三态;换代按「先 null 卸载、clearAppContext、再写新代次」顺序 |
70
+ | `MFU-030` | 桥接路由同步配置/前缀冲突报错 | basePath 非法(空/根/带 query·hash·通配)或同页重叠前缀登记 | basePath 用宿主路由视角的静态绝对路径(如 `/approval`);同页各同步实例前缀不重叠 |
71
+ | `MFU-031` | 桥接报路由协议缺失/通道失效 | 宿主启用 routing 但子应用未声明 `{ routing: true }`;或通道销毁后复用/再订阅 | 子应用契约第二参数声明 `{ routing: true }` 并从 `ctx.routing` 接线;换会话/卸载后不复活旧通道 |
72
+ | `MFU-032` | 桥接报非法导航 | 子应用导航目标越界自身前缀(`../`、跨前缀)、非法 `go` 参数、或失效通道的请求 | 子应用只导航自身 basePath 内的位置;go 参数用合法整数;通道作废后不再发起导航 |
73
+ | `MFU-033` | 桥接报路由准备/同步失败(附目标链/cause,不静默回退 memory) | 守卫/加载器/端口执行异常拒绝、或连续内部 replace 超过 5 次(重定向环) | 修复子应用守卫/加载器异常;排查重定向环(子应用路由定义的循环重定向) |
74
+
75
+ #### CC 跨应用上下文
76
+
77
+ | 码 | 现象 | 原因 | 修法 |
78
+ |---|---|---|---|
79
+ | `CC-001` | 远程初始化抛三段式错误(got / expected / example) | `requireAppContext(...)` 请求的必需字段在 AppContext 缺失 | 宿主桥在加载远程前 `provideAppContext({...})` 写入缺失字段(见[API 参考 · AppContext](api.md#2-appcontext--跨应用传值与方法引用)) |
80
+ | `CC-002` | 远程页报运行时单例不可用 | 远程页面被独立直开(未经宿主联邦加载)——没有页面级运行时与 context | 经宿主联邦加载远程页;时序契约 bridge → 远程 setup → 页面模块 |
81
+
82
+ ## 排查入口
83
+
84
+ - 按症状(不看码):[排错目录](../troubleshooting/README.md)
85
+ - 配置期错误先跑 `npx fulgurjs explain`;部署面问题先跑 `npx fulgurjs doctor`
86
+ - 运行时诊断:`window.__FULGURJS_INFO__`(各 remote 状态与 setup 阶段)、`window.__FULGURJS_SCOPE__`(shared 协商结果)、`fulgurjs:error` 事件
@@ -1,6 +1,6 @@
1
1
  # fulgurjs-federation 模板(examples/templates/)
2
2
 
3
- 五个可独立复制、`pnpm install` 后直接运行的联邦接入模板。全部使用 **npm registry 正式包** `@fulgurjs/federation@5.9.2`(精确版本 + pnpm 锁文件;5.9.3 发布时的最后已发布验证版本——5.9.3 修复 hostPages keepAlive 在 Vue 3.5 的缓存匹配,模板场景未用到 hostPages),不依赖本仓库源码、workspace 或父目录。
3
+ 五个可独立复制、`pnpm install` 后直接运行的联邦接入模板。全部使用 **npm registry 正式包** `@fulgurjs/federation@6.0.0`(精确版本 + pnpm 锁文件;6.0.0 起统一入口 /vue、/react、/runtime——模板代码即统一入口用法),不依赖本仓库源码、workspace 或父目录。
4
4
 
5
5
  ## 获取模板的两种方式
6
6
 
@@ -2,7 +2,7 @@ packages:
2
2
  - react-host
3
3
  - vue-remote
4
4
  minimumReleaseAgeExclude:
5
- - '@fulgurjs/federation@5.7.1 || 5.8.0 || 5.9.0 || 5.9.1 || 5.9.2'
5
+ - '@fulgurjs/federation@6.0.0'
6
6
  # pnpm >=12 构建脚本批准(12 起弃用 onlyBuiltDependencies;pnpm 9-11 忽略本键:
7
7
  # esbuild >=0.16 二进制经 optionalDependencies 平台包分发,postinstall 仅校验,不阻塞安装)
8
8
  allowBuilds:
@@ -1,6 +1,6 @@
1
1
  # bridge-react-host — React 宿主 × Vue 桥接子应用示例
2
2
 
3
- `@fulgurjs/federation` 跨框架桥接的 **React 18/19 宿主**侧示例:用 `createReactBridgeApp`(`@fulgurjs/federation/bridge/react`)把 `bridge-vue-remote/bridge` 作为受控组件挂载(入口跑在 StrictMode 下,双 effect 安全由契约保证)。
3
+ `@fulgurjs/federation` 跨框架桥接的 **React 18/19 宿主**侧示例:用 `createReactBridgeApp`(统一入口 `@fulgurjs/federation/react`)把 `bridge-vue-remote/bridge` 作为受控组件挂载(入口跑在 StrictMode 下,双 effect 安全由契约保证)。
4
4
 
5
5
  ## 运行
6
6
 
@@ -18,7 +18,7 @@ pnpm build # 构建完整组合
18
18
  ## 关键点(对应 README §8.2)
19
19
 
20
20
  - **双框架安装合同**:本宿主同时安装 `react` + `react-dom` + `vue`,shared 三键全部 `singleton: true`。
21
- - **入口选择**:`@fulgurjs/federation/bridge/react` 只携带 React 宿主适配器(零 Vue)。
21
+ - **入口选择**:统一入口 `@fulgurjs/federation/react`——宿主代码全部来自 /react,不会加载 Vue 适配代码(6.0.0 起 /bridge、/bridge/* 深层入口已移除)。
22
22
  - **工厂选项**:`fallback`(加载中占位)、`error`(节点或 `(error, retry) => ReactNode`)、`retries`、`timeout`、`getContext`(同步纯 getter)。
23
23
  - **换账号/登出**:受控 `sessionKey` 置 `null` → 等卸载 → `clearAppContext()` → 登录新账号 → 更新受控 prop。
24
24
  - 子应用首次根提交前发生错误 → MFU-016(phase: mount)占位;首次提交后子应用内部错误由子应用自己的错误边界负责(跨 root 不冒泡)。
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5304 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.9.2",
12
+ "@fulgurjs/federation": "6.0.0",
13
13
  "react": "^19.1.0",
14
14
  "react-dom": "^19.1.0",
15
15
  "vue": "^3.5.13"
@@ -1,7 +1,7 @@
1
1
  import { StrictMode, useCallback, useState } from 'react'
2
2
  import { createRoot } from 'react-dom/client'
3
3
  import { clearAppContext } from '@fulgurjs/federation/react'
4
- import { createReactBridgeApp } from '@fulgurjs/federation/bridge/react'
4
+ import { createReactBridgeApp } from '@fulgurjs/federation/react'
5
5
  import { getLatestHostContext, login, logout } from './host-session'
6
6
 
7
7
  // 工厂选项:fallback(pending 占位)、error(节点或 (error, retry) => ReactNode)、
@@ -42,7 +42,7 @@ function Host() {
42
42
 
43
43
  return (
44
44
  <div style={{ fontFamily: 'sans-serif', padding: 16, maxWidth: 720 }}>
45
- <h1>React 宿主 × Vue 子应用(@fulgurjs/federation/bridge/react)</h1>
45
+ <h1>React 宿主 × Vue 子应用(@fulgurjs/federation/react)</h1>
46
46
  <p data-testid="demo-session">{`会话:${sessionKey ?? '未登录'}(${userName || '—'})· onReady 次数:${readyCount}`}</p>
47
47
  <p>
48
48
  <button data-testid="demo-switch" onClick={() => void switchUser()}>切换到 Bob(clearAppContext → 重挂)</button>
@@ -1,6 +1,15 @@
1
1
  {
2
2
  "apps": [
3
- { "name": "vue-remote", "dir": "vue-remote", "port": 5313 },
4
- { "name": "react-host", "dir": "react-host", "port": 5304 }
3
+ {
4
+ "name": "vue-remote",
5
+ "dir": "vue-remote",
6
+ "port": 5313
7
+ },
8
+ {
9
+ "name": "react-host",
10
+ "dir": "react-host",
11
+ "port": 5304,
12
+ "host": true
13
+ }
5
14
  ]
6
15
  }
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5313 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.9.2",
12
+ "@fulgurjs/federation": "6.0.0",
13
13
  "vue": "^3.5.13",
14
14
  "vue-router": "^4.5.0"
15
15
  },
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { createApp, defineComponent, h, ref } from 'vue'
8
8
  import { createMemoryHistory, createRouter, RouterView, useRoute, useRouter } from 'vue-router'
9
- import { defineBridgeApp } from '@fulgurjs/federation/runtime'
9
+ import { defineBridgeApp } from '@fulgurjs/federation/vue'
10
10
 
11
11
  /** props 类型:appProps 由宿主传入(label + 稳定回调 onReady) */
12
12
  export interface BridgeVueProps {
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5204 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.9.2",
12
+ "@fulgurjs/federation": "6.0.0",
13
13
  "react": "^19.1.0",
14
14
  "react-dom": "^19.1.0",
15
15
  "react-router-dom": "^7.1.0"
@@ -2,7 +2,7 @@ packages:
2
2
  - host
3
3
  - remote
4
4
  minimumReleaseAgeExclude:
5
- - '@fulgurjs/federation@5.7.1 || 5.8.0 || 5.9.0 || 5.9.1 || 5.9.2'
5
+ - '@fulgurjs/federation@6.0.0'
6
6
  # pnpm >=12 构建脚本批准(12 起弃用 onlyBuiltDependencies;pnpm 9-11 忽略本键:
7
7
  # esbuild >=0.16 二进制经 optionalDependencies 平台包分发,postinstall 仅校验,不阻塞安装)
8
8
  allowBuilds:
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5203 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.9.2",
12
+ "@fulgurjs/federation": "6.0.0",
13
13
  "react": "^19.1.0",
14
14
  "react-dom": "^19.1.0"
15
15
  },
@@ -1,6 +1,15 @@
1
1
  {
2
2
  "apps": [
3
- { "name": "remote", "dir": "remote", "port": 5203 },
4
- { "name": "host", "dir": "host", "port": 5204 }
3
+ {
4
+ "name": "remote",
5
+ "dir": "remote",
6
+ "port": 5203
7
+ },
8
+ {
9
+ "name": "host",
10
+ "dir": "host",
11
+ "port": 5204,
12
+ "host": true
13
+ }
5
14
  ]
6
15
  }
@@ -81,12 +81,12 @@ curl --noproxy '*' -s -o /dev/null -w '%{http_code}\n' http://localhost:5335/@fu
81
81
 
82
82
  | 插件公开 API | 入口 | 本演示接线位置 |
83
83
  |---|---|---|
84
- | `createVueBridgeApp(spec, options)` | `@fulgurjs/federation/bridge/vue` | `vue-host/src/pages/BridgeReactPage.vue`(`<RemoteReactBridge :routing="routing" :app-props="appProps" />`) |
85
- | `createVueBridgeNavigation(router)` | `@fulgurjs/federation/bridge/router/vue` | `vue-host/src/routing.ts`(模块级单例端口,main.ts 组装后 `initBridgeRouting(router)`) |
86
- | `connectVueBridgeRouter(routing, router, { signal })` → `await conn.ready` 后 `app.use(router)` | `@fulgurjs/federation/bridge/router/vue` | `vue-remote/src/bridge.ts`(异步工厂:初始 push 落定后再 install,顺序不能反) |
87
- | `createReactBridgeApp(spec, options)` | `@fulgurjs/federation/bridge/react` | `react-host/src/pages/BridgeVuePage.tsx`(`<RemoteVueBridge routing={routing} appProps={appProps} />`) |
88
- | `createReactBridgeNavigation(router, { canNavigate?, basename? })`(仅 data router) | `@fulgurjs/federation/bridge/router/react` | `react-host/src/routing.ts`(`createBrowserRouter` 实例组装后初始化) |
89
- | `createReactBridgeRouter(routing, routes, { signal })` → `{ element }` 直接作为工厂返回值 | `@fulgurjs/federation/bridge/router/react` | `react-remote/src/bridge.tsx`(`/` 经 loader `redirect('/orders')` 以 replace 规范化) |
84
+ | `createVueBridgeApp(spec, options)` | `@fulgurjs/federation/vue` | `vue-host/src/pages/BridgeReactPage.vue`(`<RemoteReactBridge :routing="routing" :app-props="appProps" />`) |
85
+ | `createVueBridgeNavigation(router)` | `@fulgurjs/federation/vue` | `vue-host/src/routing.ts`(模块级单例端口,main.ts 组装后 `initBridgeRouting(router)`) |
86
+ | `connectVueBridgeRouter(routing, router, { signal })` → `await conn.ready` 后 `app.use(router)` | `@fulgurjs/federation/vue` | `vue-remote/src/bridge.ts`(异步工厂:初始 push 落定后再 install,顺序不能反) |
87
+ | `createReactBridgeApp(spec, options)` | `@fulgurjs/federation/react` | `react-host/src/pages/BridgeVuePage.tsx`(`<RemoteVueBridge routing={routing} appProps={appProps} />`) |
88
+ | `createReactBridgeNavigation(router, { canNavigate?, basename? })`(仅 data router) | `@fulgurjs/federation/react` | `react-host/src/routing.ts`(`createBrowserRouter` 实例组装后初始化) |
89
+ | `createReactBridgeRouter(routing, routes, { signal })` → `{ element }` 直接作为工厂返回值 | `@fulgurjs/federation/react` | `react-remote/src/bridge.tsx`(`/` 经 loader `redirect('/orders')` 以 replace 规范化) |
90
90
  | `defineBridgeApp(factory, { routing: true })`(协议声明,缺失即 MFU-031) | `@fulgurjs/federation/runtime`(Vue)/ `@fulgurjs/federation/react`(React) | `vue-remote/src/bridge.ts`、`react-remote/src/bridge.tsx`(工厂内校验 `ctx?.routing`,`ctx.signal` 传入接线自动 dispose) |
91
91
  | `BridgeHostRouting`(`{ basePath, navigation }` 组件 prop,独立控制通道不进 appProps) | 类型面见 README §8.3 | `vue-host/src/routing.ts`、`react-host/src/routing.ts`(basePath 常量 `BRIDGE_BASE_PATH`) |
92
92
  | `BridgeChildRoute` / `BridgeLocation`(通道与位置契约) | `/bridge/router/*` | 由插件随 mount 第三参数注入子应用;两端仓库源码 `packages/plugin/src/bridge-router-core.ts` |
@@ -4,7 +4,7 @@ packages:
4
4
  - react-host
5
5
  - react-remote
6
6
  minimumReleaseAgeExclude:
7
- - '@fulgurjs/federation@5.7.1 || 5.8.0 || 5.9.0 || 5.9.1 || 5.9.2'
7
+ - '@fulgurjs/federation@6.0.0'
8
8
  # pnpm >=12 构建脚本批准(12 起弃用 onlyBuiltDependencies;pnpm 9-11 忽略本键:
9
9
  # esbuild >=0.16 二进制经 optionalDependencies 平台包分发,postinstall 仅校验,不阻塞安装)
10
10
  allowBuilds:
@@ -10,7 +10,7 @@
10
10
  "typecheck": "tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@fulgurjs/federation": "5.9.2",
13
+ "@fulgurjs/federation": "6.0.0",
14
14
  "react": "^19.1.0",
15
15
  "react-dom": "^19.1.0",
16
16
  "react-router-dom": "^7.1.0",
@@ -7,7 +7,7 @@
7
7
  import { useState } from 'react'
8
8
  import type { ChangeEvent, ReactElement } from 'react'
9
9
  import { useLocation, useNavigate } from 'react-router-dom'
10
- import { createReactBridgeApp } from '@fulgurjs/federation/bridge/react'
10
+ import { createReactBridgeApp } from '@fulgurjs/federation/react'
11
11
  import { BRIDGE_BASE_PATH, getBridgeRouting } from '../routing'
12
12
  import { handleChildEvent, logNav } from '../demo-log'
13
13
  import ObsPanel from '../ObsPanel'
@@ -4,7 +4,7 @@
4
4
  * dev 下 Vite base 为 '/' 无需 basename;子目录部署时与 createBrowserRouter 同源传 basename。
5
5
  * 端口引用保持稳定 → routing 键不变,宿主不重挂、不重复订阅。
6
6
  */
7
- import { createReactBridgeNavigation } from '@fulgurjs/federation/bridge/router/react'
7
+ import { createReactBridgeNavigation } from '@fulgurjs/federation/react'
8
8
 
9
9
  export const BRIDGE_BASE_PATH = '/br-vue'
10
10
 
@@ -10,7 +10,7 @@
10
10
  "typecheck": "tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@fulgurjs/federation": "5.9.2",
13
+ "@fulgurjs/federation": "6.0.0",
14
14
  "react": "^19.1.0",
15
15
  "react-dom": "^19.1.0",
16
16
  "react-router-dom": "^7.1.0"
@@ -7,7 +7,7 @@
7
7
  import type { ReactElement } from 'react'
8
8
  import { redirect } from 'react-router-dom'
9
9
  import { defineBridgeApp } from '@fulgurjs/federation/react'
10
- import { createReactBridgeRouter } from '@fulgurjs/federation/bridge/router/react'
10
+ import { createReactBridgeRouter } from '@fulgurjs/federation/react'
11
11
  import ChildLayout from './ChildLayout'
12
12
  import OrderList from './pages/OrderList'
13
13
  import OrderDetail from './pages/OrderDetail'
@@ -1,8 +1,26 @@
1
1
  {
2
2
  "apps": [
3
- { "name": "vue-remote", "dir": "vue-remote", "port": 5335 },
4
- { "name": "react-remote", "dir": "react-remote", "port": 5333 },
5
- { "name": "vue-host", "dir": "vue-host", "port": 5334 },
6
- { "name": "react-host", "dir": "react-host", "port": 5336 }
3
+ {
4
+ "name": "vue-remote",
5
+ "dir": "vue-remote",
6
+ "port": 5335
7
+ },
8
+ {
9
+ "name": "react-remote",
10
+ "dir": "react-remote",
11
+ "port": 5333
12
+ },
13
+ {
14
+ "name": "vue-host",
15
+ "dir": "vue-host",
16
+ "port": 5334,
17
+ "host": true
18
+ },
19
+ {
20
+ "name": "react-host",
21
+ "dir": "react-host",
22
+ "port": 5336,
23
+ "host": true
24
+ }
7
25
  ]
8
26
  }
@@ -10,7 +10,7 @@
10
10
  "typecheck": "vue-tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@fulgurjs/federation": "5.9.2",
13
+ "@fulgurjs/federation": "6.0.0",
14
14
  "react": "^19.1.0",
15
15
  "react-dom": "^19.1.0",
16
16
  "vue": "^3.5.13",
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { ref } from 'vue'
8
8
  import { useRouter } from 'vue-router'
9
- import { createVueBridgeApp } from '@fulgurjs/federation/bridge/vue'
9
+ import { createVueBridgeApp } from '@fulgurjs/federation/vue'
10
10
  import { BRIDGE_BASE_PATH, getBridgeRouting } from '../routing'
11
11
  import { handleChildEvent, logNav } from '../demo-log'
12
12
  import ObsPanel from '../ObsPanel.vue'
@@ -5,27 +5,17 @@
5
5
  * 端口引用保持稳定 → routing 键不变,宿主不重挂、不重复订阅。
6
6
  */
7
7
  import type { Router } from 'vue-router'
8
- import { createVueBridgeNavigation } from '@fulgurjs/federation/bridge/router/vue'
8
+ import { createVueBridgeNavigation, type BridgeHostRouting } from '@fulgurjs/federation/vue'
9
9
 
10
10
  export const BRIDGE_BASE_PATH = '/br-react'
11
11
 
12
- /**
13
- * 宿主 routing prop 结构(BridgeHostRouting)。
14
- * 注:5.4.1 发布包未从 /bridge/router/vue 导出 BridgeHostRouting 类型(README §8.3 示例
15
- * 与发布包类型面不一致,已知问题),这里用端口函数返回值结构化等价替代。
16
- */
17
- interface BridgeHostRoutingLike {
18
- basePath: string
19
- navigation: ReturnType<typeof createVueBridgeNavigation>
20
- }
21
-
22
- let routing: BridgeHostRoutingLike | undefined
12
+ let routing: BridgeHostRouting | undefined
23
13
 
24
14
  export function initBridgeRouting(router: Router): void {
25
15
  routing = { basePath: BRIDGE_BASE_PATH, navigation: createVueBridgeNavigation(router) }
26
16
  }
27
17
 
28
- export function getBridgeRouting(): BridgeHostRoutingLike {
18
+ export function getBridgeRouting(): BridgeHostRouting {
29
19
  if (!routing) throw new Error('桥接路由端口未初始化:请先在 main.ts 调用 initBridgeRouting(router)')
30
20
  return routing
31
21
  }
@@ -10,7 +10,7 @@
10
10
  "typecheck": "vue-tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@fulgurjs/federation": "5.9.2",
13
+ "@fulgurjs/federation": "6.0.0",
14
14
  "vue": "^3.5.13",
15
15
  "vue-router": "^4.5.0"
16
16
  },
@@ -6,8 +6,8 @@
6
6
  */
7
7
  import { createApp } from 'vue'
8
8
  import { createMemoryHistory, createRouter, type RouteRecordRaw } from 'vue-router'
9
- import { defineBridgeApp } from '@fulgurjs/federation/runtime'
10
- import { connectVueBridgeRouter } from '@fulgurjs/federation/bridge/router/vue'
9
+ import { defineBridgeApp } from '@fulgurjs/federation/vue'
10
+ import { connectVueBridgeRouter } from '@fulgurjs/federation/vue'
11
11
  import ChildLayout from './ChildLayout.vue'
12
12
  import OrderList from './pages/OrderList.vue'
13
13
  import OrderDetail from './pages/OrderDetail.vue'
@@ -2,7 +2,7 @@ packages:
2
2
  - vue-host
3
3
  - react-remote
4
4
  minimumReleaseAgeExclude:
5
- - '@fulgurjs/federation@5.7.1 || 5.8.0 || 5.9.0 || 5.9.1 || 5.9.2'
5
+ - '@fulgurjs/federation@6.0.0'
6
6
  # pnpm >=12 构建脚本批准(12 起弃用 onlyBuiltDependencies;pnpm 9-11 忽略本键:
7
7
  # esbuild >=0.16 二进制经 optionalDependencies 平台包分发,postinstall 仅校验,不阻塞安装)
8
8
  allowBuilds:
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5303 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.9.2",
12
+ "@fulgurjs/federation": "6.0.0",
13
13
  "react": "^19.1.0",
14
14
  "react-dom": "^19.1.0",
15
15
  "react-router-dom": "^7.1.0"
@@ -1,6 +1,15 @@
1
1
  {
2
2
  "apps": [
3
- { "name": "react-remote", "dir": "react-remote", "port": 5303 },
4
- { "name": "vue-host", "dir": "vue-host", "port": 5314 }
3
+ {
4
+ "name": "react-remote",
5
+ "dir": "react-remote",
6
+ "port": 5303
7
+ },
8
+ {
9
+ "name": "vue-host",
10
+ "dir": "vue-host",
11
+ "port": 5314,
12
+ "host": true
13
+ }
5
14
  ]
6
15
  }
@@ -1,6 +1,6 @@
1
1
  # bridge-vue-host — Vue 宿主 × React 桥接子应用示例
2
2
 
3
- `@fulgurjs/federation` 跨框架桥接的 **Vue 3 宿主**侧示例:用 `createVueBridgeApp`(`@fulgurjs/federation/bridge/vue`)把 `bridge-react-remote/bridge` 作为受控组件挂载。
3
+ `@fulgurjs/federation` 跨框架桥接的 **Vue 3 宿主**侧示例:用 `createVueBridgeApp`(统一入口 `@fulgurjs/federation/vue`)把 `bridge-react-remote/bridge` 作为受控组件挂载。
4
4
 
5
5
  ## 运行
6
6
 
@@ -18,7 +18,7 @@ pnpm build # 构建完整组合
18
18
  ## 关键点(对应 README §8.2)
19
19
 
20
20
  - **双框架安装合同**:本宿主同时安装 `vue` + `react` + `react-dom`,shared 三键全部 `singleton: true`。
21
- - **入口选择**:`@fulgurjs/federation/bridge/vue` 只携带 Vue 宿主适配器——dev 原生 ESM 与生产构建都不会加载 React 宿主适配代码(聚合入口 `/bridge` 会同时执行两者,仅兼容保留)。
21
+ - **入口选择**:统一入口 `@fulgurjs/federation/vue`——宿主代码全部来自 /vue,不会加载 React 适配代码(6.0.0 起 /bridge、/bridge/* 深层入口已移除)。
22
22
  - **`sessionKey`**:受控登录代次(非业务 props)。置 `null` = 登出态(立即卸载、不再请求);换账号走「null → `clearAppContext()` → 新代次」顺序,保证 A 的 context 字段零残留。
23
23
  - **`getContext`**:同步纯 getter(`src/host-session.ts`),桥接层校验其快照的 `sessionKey` 后才代写 AppContext。
24
24
  - **`appProps`**:挂载时浅拷贝快照;函数引用(`onReady`)保留原引用;换顶层引用不重挂,需要重置时用 `:key`。
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5314 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.9.2",
12
+ "@fulgurjs/federation": "6.0.0",
13
13
  "react": "^19.1.0",
14
14
  "react-dom": "^19.1.0",
15
15
  "vue": "^3.5.13"
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { ref } from 'vue'
7
7
  import { clearAppContext } from '@fulgurjs/federation/runtime'
8
- import { createVueBridgeApp } from '@fulgurjs/federation/bridge/vue'
8
+ import { createVueBridgeApp } from '@fulgurjs/federation/vue'
9
9
  import { getLatestHostContext, login, logout } from './host-session'
10
10
 
11
11
  // 工厂选项:retries 透传 loadRemote;getContext 在每次实际加载前同步取最新快照
@@ -51,7 +51,7 @@ async function doLogout(): Promise<void> {
51
51
 
52
52
  <template>
53
53
  <div style="font-family: sans-serif; padding: 16px; max-width: 720px">
54
- <h1>Vue 宿主 × React 子应用(@fulgurjs/federation/bridge/vue)</h1>
54
+ <h1>Vue 宿主 × React 子应用(@fulgurjs/federation/vue)</h1>
55
55
  <p data-testid="demo-session">会话:{{ sessionKey ?? '未登录' }}({{ userName || '—' }})· onReady 次数:{{ readyCount }}</p>
56
56
 
57
57
  <p>
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5214 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.9.2",
12
+ "@fulgurjs/federation": "6.0.0",
13
13
  "vue": "^3.5.13",
14
14
  "vue-router": "^4.5.0"
15
15
  },
@@ -1,6 +1,6 @@
1
1
  import { createApp, h } from 'vue'
2
2
  import { createRouter, createWebHistory, useRoute } from 'vue-router'
3
- import { createHostPages } from '@fulgurjs/federation/runtime'
3
+ import { createHostPages } from '@fulgurjs/federation/vue'
4
4
  import App from './App.vue'
5
5
  import HomePage from './pages/HomePage.vue'
6
6
  import UtilsDemo from './pages/UtilsDemo.vue'
@@ -13,31 +13,38 @@ const hostPages = createHostPages({
13
13
  remotePrefixes,
14
14
  })
15
15
 
16
+ // 远程页面 Router 记录从页面表派生(route + spec 唯一来源 = fulgurjs.config.ts 的 pages;
17
+ // 业务自有路由仍归本 Router 管理——业务 Router 与联邦页面映射是两类事实)。
18
+ // 远程名按最长前缀从 remotePrefixes 解析(与运行时归属一致);params + query 全量透传给
19
+ // 远程页面组件(响应式:路由变化即重渲染)。
20
+ const remoteNameOf = (route: string): string => {
21
+ const prefix = Object.keys(remotePrefixes)
22
+ .filter((p) => route === p || route.startsWith(p + '/') || route.startsWith(p))
23
+ .sort((a, b) => b.length - a.length)[0]
24
+ const name = prefix ? remotePrefixes[prefix] : undefined
25
+ if (!name) throw new Error(`页面 ${route} 不匹配任何 remotePrefixes 前缀——请核对 fulgurjs.config.ts`)
26
+ return name
27
+ }
28
+ const remoteRoutes = pages.map((page) => ({
29
+ path: page.route,
30
+ component: {
31
+ setup() {
32
+ const route = useRoute()
33
+ return () =>
34
+ h(hostPages.component(`${remoteNameOf(page.route)}/${page.spec}`), {
35
+ ...route.params,
36
+ ...route.query,
37
+ })
38
+ },
39
+ },
40
+ }))
41
+
16
42
  const router = createRouter({
17
43
  history: createWebHistory(),
18
44
  routes: [
19
45
  { path: '/', component: HomePage },
20
46
  { path: '/utils-demo', component: UtilsDemo },
21
- {
22
- // 远程页面:spec 经 hostPages.component(spec) 取异步组件(spec = 远程名 + exposes 键);
23
- // route.params + route.query 作为 props 透传给远程页面组件
24
- path: '/remote/home',
25
- component: { render: () => h(hostPages.component('vue-remote/pages/HomePage')) },
26
- },
27
- {
28
- path: '/remote/detail/:id',
29
- // params + query 全量透传给远程页面组件(响应式:路由变化即重渲染)
30
- component: {
31
- setup() {
32
- const route = useRoute()
33
- return () =>
34
- h(hostPages.component('vue-remote/pages/DetailPage'), {
35
- id: route.params.id as string,
36
- tab: (route.query.tab as string | undefined) ?? undefined,
37
- })
38
- },
39
- },
40
- },
47
+ ...remoteRoutes,
41
48
  ],
42
49
  })
43
50