@fulgurjs/federation 5.8.0 → 5.9.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 (216) hide show
  1. package/CHANGELOG.md +14 -4
  2. package/README.en.md +60 -24
  3. package/README.md +60 -24
  4. package/dist/cli.js +327 -29
  5. package/dist/index.cjs +2 -2
  6. package/dist/index.js +2 -2
  7. package/dist/runtime.js +1 -1
  8. package/docs/API.en.md +14 -3
  9. package/docs/API.md +7 -6
  10. package/docs/webpack-mf-/345/257/271/347/205/247/344/270/216/347/274/272/345/217/243.md +2 -2
  11. package/examples/README.md +3 -67
  12. package/examples/templates/README.md +88 -0
  13. package/examples/templates/react-host-vue-remote/README.md +18 -0
  14. package/examples/templates/react-host-vue-remote/package.json +11 -0
  15. package/examples/templates/react-host-vue-remote/pnpm-lock.yaml +1627 -0
  16. package/examples/templates/react-host-vue-remote/pnpm-workspace.yaml +10 -0
  17. package/examples/{bridge → templates/react-host-vue-remote}/react-host/README.md +8 -7
  18. package/examples/{bridge → templates/react-host-vue-remote}/react-host/package.json +1 -1
  19. package/examples/templates/react-host-vue-remote/react-host/src/fulgurjs/types/bridge-vue-remote.d/_paths.d.ts +4 -0
  20. package/examples/templates/react-host-vue-remote/react-host/src/fulgurjs/types/bridge-vue-remote.d/bridge.ts +3 -0
  21. package/examples/templates/react-host-vue-remote/react-host/src/fulgurjs/types/bridge-vue-remote.d.ts +9 -0
  22. package/examples/templates/react-host-vue-remote/scripts/dev.config.json +6 -0
  23. package/examples/templates/react-host-vue-remote/scripts/dev.mjs +173 -0
  24. package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/README.md +10 -5
  25. package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/package.json +1 -1
  26. package/examples/{react → templates/react-react}/README.md +9 -13
  27. package/examples/{react → templates/react-react}/host/README.md +6 -8
  28. package/examples/{react → templates/react-react}/host/package.json +1 -1
  29. package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/ClickButton.ts +3 -0
  30. package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/_paths.d.ts +4 -0
  31. package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/pages/DetailPage.ts +3 -0
  32. package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/pages/HomePage.ts +3 -0
  33. package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/utils.ts +2 -0
  34. package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d.ts +26 -0
  35. package/examples/templates/react-react/package.json +11 -0
  36. package/examples/templates/react-react/pnpm-lock.yaml +1537 -0
  37. package/examples/templates/react-react/pnpm-workspace.yaml +10 -0
  38. package/examples/{react → templates/react-react}/remote/README.md +7 -6
  39. package/examples/{react → templates/react-react}/remote/package.json +1 -1
  40. package/examples/templates/react-react/scripts/dev.config.json +6 -0
  41. package/examples/templates/react-react/scripts/dev.mjs +173 -0
  42. package/examples/templates/showcase/README.md +109 -0
  43. package/examples/templates/showcase/package.json +13 -0
  44. package/examples/templates/showcase/pnpm-lock.yaml +1858 -0
  45. package/examples/templates/showcase/pnpm-workspace.yaml +12 -0
  46. package/examples/templates/showcase/react-host/fulgurjs.config.ts +21 -0
  47. package/examples/templates/showcase/react-host/index.html +13 -0
  48. package/examples/templates/showcase/react-host/package.json +26 -0
  49. package/examples/templates/showcase/react-host/src/GuardBanner.tsx +33 -0
  50. package/examples/templates/showcase/react-host/src/Layout.tsx +42 -0
  51. package/examples/templates/showcase/react-host/src/ObsPanel.tsx +44 -0
  52. package/examples/templates/showcase/react-host/src/demo-log.ts +74 -0
  53. package/examples/templates/showcase/react-host/src/fulgurjs/types/vue-remote.d/_paths.d.ts +4 -0
  54. package/examples/templates/showcase/react-host/src/fulgurjs/types/vue-remote.d/bridge.ts +3 -0
  55. package/examples/templates/showcase/react-host/src/fulgurjs/types/vue-remote.d.ts +7 -0
  56. package/examples/templates/showcase/react-host/src/main.tsx +33 -0
  57. package/examples/templates/showcase/react-host/src/pages/AboutPage.tsx +18 -0
  58. package/examples/templates/showcase/react-host/src/pages/BridgeVuePage.tsx +77 -0
  59. package/examples/templates/showcase/react-host/src/pages/HomePage.tsx +14 -0
  60. package/examples/templates/showcase/react-host/src/routing.ts +30 -0
  61. package/examples/templates/showcase/react-host/tsconfig.json +15 -0
  62. package/examples/templates/showcase/react-host/vite.config.ts +8 -0
  63. package/examples/templates/showcase/react-remote/fulgurjs.config.ts +18 -0
  64. package/examples/templates/showcase/react-remote/index.html +13 -0
  65. package/examples/templates/showcase/react-remote/package.json +25 -0
  66. package/examples/templates/showcase/react-remote/src/ChildLayout.tsx +48 -0
  67. package/examples/templates/showcase/react-remote/src/bridge.tsx +62 -0
  68. package/examples/templates/showcase/react-remote/src/child-bus.ts +32 -0
  69. package/examples/templates/showcase/react-remote/src/main.tsx +18 -0
  70. package/examples/templates/showcase/react-remote/src/pages/Locked.tsx +23 -0
  71. package/examples/templates/showcase/react-remote/src/pages/OrderDetail.tsx +36 -0
  72. package/examples/templates/showcase/react-remote/src/pages/OrderList.tsx +110 -0
  73. package/examples/templates/showcase/react-remote/src/pages/Settings.tsx +50 -0
  74. package/examples/templates/showcase/react-remote/src/settings-store.ts +11 -0
  75. package/examples/templates/showcase/react-remote/tsconfig.json +14 -0
  76. package/examples/templates/showcase/react-remote/vite.config.ts +14 -0
  77. package/examples/templates/showcase/scripts/dev.config.json +8 -0
  78. package/examples/templates/showcase/scripts/dev.mjs +173 -0
  79. package/examples/templates/showcase/vue-host/fulgurjs.config.ts +21 -0
  80. package/examples/templates/showcase/vue-host/index.html +13 -0
  81. package/examples/templates/showcase/vue-host/package.json +25 -0
  82. package/examples/templates/showcase/vue-host/src/App.vue +50 -0
  83. package/examples/templates/showcase/vue-host/src/GuardBanner.vue +24 -0
  84. package/examples/templates/showcase/vue-host/src/ObsPanel.vue +60 -0
  85. package/examples/templates/showcase/vue-host/src/demo-log.ts +49 -0
  86. package/examples/templates/showcase/vue-host/src/fulgurjs/types/react-remote.d/_paths.d.ts +4 -0
  87. package/examples/templates/showcase/vue-host/src/fulgurjs/types/react-remote.d/bridge.ts +3 -0
  88. package/examples/templates/showcase/vue-host/src/fulgurjs/types/react-remote.d.ts +7 -0
  89. package/examples/templates/showcase/vue-host/src/guard.ts +47 -0
  90. package/examples/templates/showcase/vue-host/src/main.ts +30 -0
  91. package/examples/templates/showcase/vue-host/src/pages/AboutPage.vue +17 -0
  92. package/examples/templates/showcase/vue-host/src/pages/BridgeReactPage.vue +74 -0
  93. package/examples/templates/showcase/vue-host/src/pages/HomePage.vue +13 -0
  94. package/examples/templates/showcase/vue-host/src/routing.ts +31 -0
  95. package/examples/templates/showcase/vue-host/tsconfig.json +14 -0
  96. package/examples/templates/showcase/vue-remote/fulgurjs.config.ts +17 -0
  97. package/examples/templates/showcase/vue-remote/index.html +13 -0
  98. package/examples/templates/showcase/vue-remote/package.json +23 -0
  99. package/examples/templates/showcase/vue-remote/src/ChildLayout.vue +54 -0
  100. package/examples/templates/showcase/vue-remote/src/bridge.ts +48 -0
  101. package/examples/templates/showcase/vue-remote/src/child-bus.ts +32 -0
  102. package/examples/templates/showcase/vue-remote/src/main.ts +16 -0
  103. package/examples/templates/showcase/vue-remote/src/pages/Locked.vue +28 -0
  104. package/examples/templates/showcase/vue-remote/src/pages/OrderDetail.vue +46 -0
  105. package/examples/templates/showcase/vue-remote/src/pages/OrderList.vue +116 -0
  106. package/examples/templates/showcase/vue-remote/src/pages/Settings.vue +34 -0
  107. package/examples/templates/showcase/vue-remote/src/settings-store.ts +13 -0
  108. package/examples/templates/showcase/vue-remote/tsconfig.json +14 -0
  109. package/examples/templates/showcase/vue-remote/vite.config.ts +14 -0
  110. package/examples/templates/vue-host-react-remote/README.md +18 -0
  111. package/examples/templates/vue-host-react-remote/package.json +11 -0
  112. package/examples/templates/vue-host-react-remote/pnpm-lock.yaml +1663 -0
  113. package/examples/templates/vue-host-react-remote/pnpm-workspace.yaml +10 -0
  114. package/examples/{bridge → templates/vue-host-react-remote}/react-remote/README.md +9 -4
  115. package/examples/{bridge → templates/vue-host-react-remote}/react-remote/package.json +1 -1
  116. package/examples/templates/vue-host-react-remote/scripts/dev.config.json +6 -0
  117. package/examples/templates/vue-host-react-remote/scripts/dev.mjs +173 -0
  118. package/examples/{bridge → templates/vue-host-react-remote}/vue-host/README.md +8 -7
  119. package/examples/{bridge → templates/vue-host-react-remote}/vue-host/package.json +1 -1
  120. package/examples/{bridge → templates/vue-host-react-remote}/vue-host/src/App.vue +1 -1
  121. package/examples/templates/vue-host-react-remote/vue-host/src/fulgurjs/types/bridge-react-remote.d/_paths.d.ts +4 -0
  122. package/examples/templates/vue-host-react-remote/vue-host/src/fulgurjs/types/bridge-react-remote.d/bridge.ts +3 -0
  123. package/examples/templates/vue-host-react-remote/vue-host/src/fulgurjs/types/bridge-react-remote.d.ts +9 -0
  124. package/examples/{vue → templates/vue-vue}/README.md +9 -13
  125. package/examples/{vue → templates/vue-vue}/host/README.md +6 -8
  126. package/examples/{vue → templates/vue-vue}/host/package.json +1 -1
  127. package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/ClickButton.ts +4 -0
  128. package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/_paths.d.ts +4 -0
  129. package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/pages/DetailPage.ts +4 -0
  130. package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/pages/HomePage.ts +4 -0
  131. package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/utils.ts +2 -0
  132. package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d.ts +29 -0
  133. package/examples/templates/vue-vue/host/vite.config.ts +8 -0
  134. package/examples/templates/vue-vue/package.json +11 -0
  135. package/examples/templates/vue-vue/pnpm-lock.yaml +1199 -0
  136. package/examples/templates/vue-vue/pnpm-workspace.yaml +10 -0
  137. package/examples/{vue → templates/vue-vue}/remote/README.md +7 -6
  138. package/examples/{vue → templates/vue-vue}/remote/package.json +1 -1
  139. package/examples/{vue → templates/vue-vue}/remote/src/App.vue +1 -1
  140. package/examples/templates/vue-vue/scripts/dev.config.json +6 -0
  141. package/examples/templates/vue-vue/scripts/dev.mjs +173 -0
  142. package/package.json +4 -4
  143. package/examples/README.en.md +0 -67
  144. package/examples/bridge/README.md +0 -36
  145. package/examples/bridge/react-host/package-lock.json +0 -2466
  146. package/examples/bridge/react-remote/package-lock.json +0 -2391
  147. package/examples/bridge/vue-host/package-lock.json +0 -1894
  148. package/examples/bridge/vue-remote/package-lock.json +0 -1865
  149. package/examples/react/host/package-lock.json +0 -2391
  150. package/examples/react/remote/package-lock.json +0 -2333
  151. package/examples/vue/host/package-lock.json +0 -1865
  152. package/examples/vue/remote/package-lock.json +0 -1843
  153. /package/examples/{bridge → templates/react-host-vue-remote}/react-host/fulgurjs.config.ts +0 -0
  154. /package/examples/{bridge → templates/react-host-vue-remote}/react-host/index.html +0 -0
  155. /package/examples/{bridge → templates/react-host-vue-remote}/react-host/src/env.d.ts +0 -0
  156. /package/examples/{bridge → templates/react-host-vue-remote}/react-host/src/host-session.ts +0 -0
  157. /package/examples/{bridge → templates/react-host-vue-remote}/react-host/src/main.tsx +0 -0
  158. /package/examples/{bridge → templates/react-host-vue-remote}/react-host/tsconfig.json +0 -0
  159. /package/examples/{bridge → templates/react-host-vue-remote}/react-host/vite.config.ts +0 -0
  160. /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/fulgurjs.config.ts +0 -0
  161. /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/index.html +0 -0
  162. /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/src/App.vue +0 -0
  163. /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/src/bridge.ts +0 -0
  164. /package/examples/{bridge/react-remote → templates/react-host-vue-remote/vue-remote}/src/env.d.ts +0 -0
  165. /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/src/main.ts +0 -0
  166. /package/examples/{bridge/vue-host → templates/react-host-vue-remote/vue-remote}/tsconfig.json +0 -0
  167. /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/vite.config.ts +0 -0
  168. /package/examples/{react → templates/react-react}/host/fulgurjs.config.ts +0 -0
  169. /package/examples/{react → templates/react-react}/host/index.html +0 -0
  170. /package/examples/{react → templates/react-react}/host/src/App.tsx +0 -0
  171. /package/examples/{react → templates/react-react}/host/src/main.tsx +0 -0
  172. /package/examples/{react → templates/react-react}/host/src/pages/UtilsDemo.tsx +0 -0
  173. /package/examples/{react → templates/react-react}/host/src/remotePages.tsx +0 -0
  174. /package/examples/{bridge/react-remote → templates/react-react/host}/tsconfig.json +0 -0
  175. /package/examples/{react → templates/react-react}/host/vite.config.ts +0 -0
  176. /package/examples/{react → templates/react-react}/remote/fulgurjs.config.ts +0 -0
  177. /package/examples/{react → templates/react-react}/remote/index.html +0 -0
  178. /package/examples/{react → templates/react-react}/remote/src/App.tsx +0 -0
  179. /package/examples/{react → templates/react-react}/remote/src/exposes/ClickButton.tsx +0 -0
  180. /package/examples/{react → templates/react-react}/remote/src/exposes/pages/DetailPage.tsx +0 -0
  181. /package/examples/{react → templates/react-react}/remote/src/exposes/pages/HomePage.tsx +0 -0
  182. /package/examples/{react → templates/react-react}/remote/src/exposes/utils.ts +0 -0
  183. /package/examples/{react → templates/react-react}/remote/src/main.tsx +0 -0
  184. /package/examples/{react/host → templates/react-react/remote}/tsconfig.json +0 -0
  185. /package/examples/{react → templates/react-react}/remote/vite.config.ts +0 -0
  186. /package/examples/{vue/host → templates/showcase/vue-host}/vite.config.ts +0 -0
  187. /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/fulgurjs.config.ts +0 -0
  188. /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/index.html +0 -0
  189. /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/src/bridge.tsx +0 -0
  190. /package/examples/{bridge/vue-host → templates/vue-host-react-remote/react-remote}/src/env.d.ts +0 -0
  191. /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/src/main.tsx +0 -0
  192. /package/examples/{react/remote → templates/vue-host-react-remote/react-remote}/tsconfig.json +0 -0
  193. /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/vite.config.ts +0 -0
  194. /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/fulgurjs.config.ts +0 -0
  195. /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/index.html +0 -0
  196. /package/examples/{bridge/vue-remote → templates/vue-host-react-remote/vue-host}/src/env.d.ts +0 -0
  197. /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/src/host-session.ts +0 -0
  198. /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/src/main.ts +0 -0
  199. /package/examples/{bridge/vue-remote → templates/vue-host-react-remote/vue-host}/tsconfig.json +0 -0
  200. /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/vite.config.ts +0 -0
  201. /package/examples/{vue → templates/vue-vue}/host/fulgurjs.config.ts +0 -0
  202. /package/examples/{vue → templates/vue-vue}/host/index.html +0 -0
  203. /package/examples/{vue → templates/vue-vue}/host/src/App.vue +0 -0
  204. /package/examples/{vue → templates/vue-vue}/host/src/main.ts +0 -0
  205. /package/examples/{vue → templates/vue-vue}/host/src/pages/HomePage.vue +0 -0
  206. /package/examples/{vue → templates/vue-vue}/host/src/pages/UtilsDemo.vue +0 -0
  207. /package/examples/{vue → templates/vue-vue}/host/tsconfig.json +0 -0
  208. /package/examples/{vue → templates/vue-vue}/remote/fulgurjs.config.ts +0 -0
  209. /package/examples/{vue → templates/vue-vue}/remote/index.html +0 -0
  210. /package/examples/{vue → templates/vue-vue}/remote/src/exposes/ClickButton.vue +0 -0
  211. /package/examples/{vue → templates/vue-vue}/remote/src/exposes/pages/DetailPage.vue +0 -0
  212. /package/examples/{vue → templates/vue-vue}/remote/src/exposes/pages/HomePage.vue +0 -0
  213. /package/examples/{vue → templates/vue-vue}/remote/src/exposes/utils.ts +0 -0
  214. /package/examples/{vue → templates/vue-vue}/remote/src/main.ts +0 -0
  215. /package/examples/{vue → templates/vue-vue}/remote/tsconfig.json +0 -0
  216. /package/examples/{vue → templates/vue-vue}/remote/vite.config.ts +0 -0
@@ -0,0 +1,10 @@
1
+ packages:
2
+ - vue-host
3
+ - react-remote
4
+ minimumReleaseAgeExclude:
5
+ - '@fulgurjs/federation@5.7.1 || 5.8.0'
6
+ # pnpm >=12 构建脚本批准(12 起弃用 onlyBuiltDependencies;pnpm 9-11 忽略本键:
7
+ # esbuild >=0.16 二进制经 optionalDependencies 平台包分发,postinstall 仅校验,不阻塞安装)
8
+ allowBuilds:
9
+ esbuild: true
10
+ vue-demi: true
@@ -1,15 +1,20 @@
1
1
  # bridge-react-remote — React 桥接子应用示例
2
2
 
3
- `@fulgurjs/federation` 跨框架桥接的 **React 18/19 子应用**侧示例:以 `defineBridgeApp`(`@fulgurjs/federation/react`)导出 `mount/unmount` 契约,可被 **Vue 宿主**(配合 `examples/bridge/vue-host`)整站挂载。
3
+ `@fulgurjs/federation` 跨框架桥接的 **React 18/19 子应用**侧示例:以 `defineBridgeApp`(`@fulgurjs/federation/react`)导出 `mount/unmount` 契约,可被 **Vue 宿主**(配合 `examples/templates/vue-host-react-remote/vue-host-react-remote/vue-host`)整站挂载。
4
4
 
5
5
  ## 运行
6
6
 
7
+ 复制整个 `vue-host-react-remote/` 模板,在模板根执行:
8
+
7
9
  ```bash
8
- npm install
9
- npm run dev # http://localhost:5303(独立运行态)
10
- npm run build # 产出 /bridge-react-remote/ 子路径产物
10
+ pnpm install --frozen-lockfile
11
+ pnpm dev # 同时启动宿主和子应用
12
+ pnpm build # 构建完整组合
13
+ # 单独启动本应用:pnpm --dir react-remote dev
11
14
  ```
12
15
 
16
+ 端口、复制范围与部署路径见[组合说明](../README.md)。
17
+
13
18
  ## 关键点
14
19
 
15
20
  - `src/bridge.tsx`:`defineBridgeApp((props) => <MemoryRouter>…</MemoryRouter>)`,作为 `./bridge` expose 的默认导出。
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5303 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.7.1",
12
+ "@fulgurjs/federation": "5.8.0",
13
13
  "react": "^19.1.0",
14
14
  "react-dom": "^19.1.0",
15
15
  "react-router-dom": "^7.1.0"
@@ -0,0 +1,6 @@
1
+ {
2
+ "apps": [
3
+ { "name": "react-remote", "dir": "react-remote", "port": 5303 },
4
+ { "name": "vue-host", "dir": "vue-host", "port": 5314 }
5
+ ]
6
+ }
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 模板统一 dev 启动器(规范源)。
4
+ *
5
+ * 本文件经 examples/scripts/sync-template-scripts.mjs 同步到五个模板的 scripts/dev.mjs;
6
+ * 模板内副本必须与规范源逐字节一致(check-catalog.mjs 校验哈希),模板复制出仓库后独立可用——
7
+ * 只依赖同目录 dev.config.json 与 Node 内置模块,不依赖仓库其他文件。
8
+ *
9
+ * 行为契约(与模板 README 一致):
10
+ * - 启动前预检全部端口:任何端口被占用则拒绝启动并指认处理方法(绝不按端口杀别人的进程);
11
+ * - 按 dev.config.json 顺序(远程在前宿主在后)启动各应用,逐个探活;
12
+ * - 任一应用启动失败/超时/中途退出:整组停止(只杀本次启动的子进程),非零退出并打印该应用日志尾部;
13
+ * - Ctrl+C / SIGTERM:清理本次启动的全部子进程后退出;不依赖 PID 文件;
14
+ * - 全部就绪后打印访问入口;探活 = 端口可连接(dev server 已监听),页面可用以浏览器验收为准。
15
+ *
16
+ * 平台:macOS/Linux 实测;Windows 走 taskkill 兜底路径,未经验证(见模板 README)。
17
+ */
18
+ import { spawn } from 'node:child_process'
19
+ import fs from 'node:fs'
20
+ import net from 'node:net'
21
+ import path from 'node:path'
22
+ import { fileURLToPath } from 'node:url'
23
+
24
+ const templateRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
25
+ const { apps, readyTimeoutMs = 120000 } = JSON.parse(
26
+ fs.readFileSync(path.join(templateRoot, 'scripts', 'dev.config.json'), 'utf8'),
27
+ )
28
+ const isTTY = process.stdout.isTTY
29
+ const color = (code, text) => (isTTY ? `\x1b[${code}m${text}\x1b[0m` : text)
30
+ const EXIT = { ok: 0, startupFailed: 1, portConflict: 2, signal: 130 }
31
+
32
+ /** 双栈端口探测(vite 可能只绑 IPv4 或 IPv6 回环) */
33
+ function isPortUp(port) {
34
+ const probe = (host) =>
35
+ new Promise((resolve, reject) => {
36
+ const s = net.connect({ port, host, timeout: 800 })
37
+ s.on('connect', () => { s.destroy(); resolve(true) })
38
+ s.on('error', reject)
39
+ s.on('timeout', () => { s.destroy(); reject(new Error('timeout')) })
40
+ })
41
+ return Promise.any([probe('127.0.0.1'), probe('::1')]).catch(() => false)
42
+ }
43
+
44
+ const tailOf = new Map()
45
+ const children = new Map()
46
+ let shuttingDown = false
47
+
48
+ function recordOutput(name, chunk) {
49
+ const lines = (tailOf.get(name) ?? [])
50
+ for (const line of String(chunk).split('\n')) {
51
+ if (line === '') continue
52
+ lines.push(line)
53
+ }
54
+ while (lines.length > 60) lines.shift()
55
+ tailOf.set(name, lines)
56
+ }
57
+
58
+ function printAppLine(name, text) {
59
+ process.stdout.write(`${color('2', `[${name}]`)} ${text}\n`)
60
+ }
61
+
62
+ async function preflight() {
63
+ const conflicts = []
64
+ for (const app of apps) {
65
+ if (await isPortUp(app.port)) conflicts.push(app)
66
+ }
67
+ if (conflicts.length === 0) return
68
+ console.error(color('31', '[dev] 启动前检查失败:以下端口已被占用(不区分占用者,一律不启动):'))
69
+ for (const app of conflicts) {
70
+ const posix = `lsof -nP -iTCP:${app.port} -sTCP:LISTEN`
71
+ const win = `netstat -ano | findstr :${app.port}`
72
+ console.error(
73
+ ` ${app.name} → 端口 ${app.port} 已监听。查看占用:${process.platform === 'win32' ? win : posix};` +
74
+ `结束占用进程,或同步修改 ${app.dir}/package.json 的 dev/preview 端口与宿主 fulgurjs.config.ts 的 remotes dev 地址后重试`,
75
+ )
76
+ }
77
+ console.error('[dev] 本启动器只清理自己启动的进程,不会替你结束端口上的既有服务。')
78
+ process.exit(EXIT.portConflict)
79
+ }
80
+
81
+ function spawnApp(app) {
82
+ const child = spawn('pnpm', ['--dir', app.dir, 'run', 'dev'], {
83
+ cwd: templateRoot,
84
+ stdio: ['ignore', 'pipe', 'pipe'],
85
+ // POSIX:独立进程组,便于整组终止;Windows:shell 解析 pnpm.cmd,树杀交给 taskkill
86
+ detached: true,
87
+ shell: process.platform === 'win32',
88
+ })
89
+ children.set(app.name, child)
90
+ child.stdout.on('data', (c) => { recordOutput(app.name, c); String(c).split('\n').filter(Boolean).forEach((l) => printAppLine(app.name, l)) })
91
+ child.stderr.on('data', (c) => { recordOutput(app.name, c); String(c).split('\n').filter(Boolean).forEach((l) => printAppLine(app.name, l)) })
92
+ return child
93
+ }
94
+
95
+ const exitedOnce = (child) =>
96
+ new Promise((resolve) => {
97
+ child.once('exit', (code, signal) => resolve({ code, signal }))
98
+ child.once('error', (e) => resolve({ code: -1, signal: null, error: e }))
99
+ })
100
+
101
+ async function waitReady(app, child) {
102
+ const exited = exitedOnce(child)
103
+ const deadline = Date.now() + readyTimeoutMs
104
+ while (Date.now() < deadline) {
105
+ if (await isPortUp(app.port)) return { ok: true }
106
+ const done = await Promise.race([exited.then(() => 'exit'), new Promise((r) => setTimeout(() => r('tick'), 400))])
107
+ if (done === 'exit') return { ok: false, reason: `进程提前退出(启动命令失败——看下方日志尾部)` }
108
+ }
109
+ return { ok: false, reason: `${Math.round(readyTimeoutMs / 1000)}s 内端口 ${app.port} 未就绪(dev server 未监听)` }
110
+ }
111
+
112
+ function killTree(appName) {
113
+ const child = children.get(appName)
114
+ if (!child || child.exitCode !== null || child.signalCode !== null) return Promise.resolve()
115
+ return new Promise((resolve) => {
116
+ const force = setTimeout(() => {
117
+ try { process.kill(process.platform === 'win32' ? child.pid : -child.pid, 'SIGKILL') } catch { /* 已退出 */ }
118
+ }, 3000).unref()
119
+ child.once('exit', () => { clearTimeout(force); resolve() })
120
+ try {
121
+ if (process.platform === 'win32') spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { stdio: 'ignore' })
122
+ else process.kill(-child.pid, 'SIGTERM')
123
+ } catch { clearTimeout(force); resolve() }
124
+ })
125
+ }
126
+
127
+ async function shutdown(exitCode, reason) {
128
+ if (shuttingDown) return
129
+ shuttingDown = true
130
+ if (reason) console.log(`[dev] ${reason}`)
131
+ console.log(`[dev] 正在停止本次启动的 ${children.size} 个应用…`)
132
+ await Promise.all([...children.keys()].map(killTree))
133
+ console.log('[dev] 已全部停止。')
134
+ process.exit(exitCode)
135
+ }
136
+
137
+ process.on('SIGINT', () => void shutdown(EXIT.signal, '[dev] 收到 Ctrl+C'))
138
+ process.on('SIGTERM', () => void shutdown(143, '[dev] 收到 SIGTERM'))
139
+
140
+ await preflight()
141
+
142
+ console.log(`[dev] 模板 ${path.basename(templateRoot)}:按顺序启动 ${apps.map((a) => a.name).join(' → ')}`)
143
+ for (const app of apps) {
144
+ printAppLine(app.name, `启动(pnpm --dir ${app.dir} run dev),等待端口 ${app.port} 就绪…`)
145
+ const child = spawnApp(app)
146
+ const ready = await waitReady(app, child)
147
+ if (!ready.ok) {
148
+ console.error(color('31', `\n[dev] 启动失败:${app.name} —— ${ready.reason}`))
149
+ const tail = tailOf.get(app.name) ?? []
150
+ if (tail.length) {
151
+ console.error(color('31', `[dev] ${app.name} 日志尾部(最后 ${tail.length} 行):`))
152
+ for (const line of tail) console.error(` [${app.name}] ${line}`)
153
+ }
154
+ await Promise.all([...children.keys()].map(killTree))
155
+ console.error(`[dev] 已停止本次启动的全部进程(${children.size} 个)。修复上面的问题后重新运行 pnpm dev。`)
156
+ process.exit(EXIT.startupFailed)
157
+ }
158
+ printAppLine(app.name, `就绪 → http://localhost:${app.port}/`)
159
+ }
160
+
161
+ console.log(color('32', '\n[dev] 全部应用已就绪:'))
162
+ for (const app of [...apps].reverse()) {
163
+ console.log(` http://localhost:${app.port}/ ${app.name}`)
164
+ }
165
+ console.log('[dev] Ctrl+C 停止全部应用(只清理本次启动的进程)。dev server 已监听 ≠ 页面必然可用,验收请以浏览器实际加载为准。\n')
166
+
167
+ // 运行期任何子应用退出(崩溃/被外部杀掉)→ 整组停止,不让半残组合冒充正常运行
168
+ for (const [name, child] of children) {
169
+ child.once('exit', (code) => {
170
+ if (!shuttingDown) void shutdown(EXIT.startupFailed, `[dev] ${name} 意外退出(退出码 ${code})——停止其余应用`)
171
+ })
172
+ }
173
+ await new Promise(() => {})
@@ -4,16 +4,17 @@
4
4
 
5
5
  ## 运行
6
6
 
7
- ```bash
8
- # 1) 先启动 React 子应用(5303)
9
- cd ../react-remote && npm install && npm run dev
7
+ 复制整个 `vue-host-react-remote/` 模板,在模板根执行:
10
8
 
11
- # 2) 再启动本宿主(5314)
12
- npm install
13
- npm run dev # http://localhost:5314
14
- npm run build # 产出 /bridge-vue-host/ 子路径产物
9
+ ```bash
10
+ pnpm install --frozen-lockfile
11
+ pnpm dev # 同时启动宿主和子应用
12
+ pnpm build # 构建完整组合
13
+ # 单独启动本应用:pnpm --dir vue-host dev
15
14
  ```
16
15
 
16
+ 端口、复制范围与部署路径见[组合说明](../README.md)。
17
+
17
18
  ## 关键点(对应 README §8.2)
18
19
 
19
20
  - **双框架安装合同**:本宿主同时安装 `vue` + `react` + `react-dom`,shared 三键全部 `singleton: true`。
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5314 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.7.1",
12
+ "@fulgurjs/federation": "5.8.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
  <script setup lang="ts">
2
2
  /**
3
3
  * Vue 宿主 × React 桥接子应用(examples 版,含全部关键语义注释)。
4
- * 先启动 examples/bridge/react-remote(5303)再启动本宿主。
4
+ * 先启动 examples/templates/react-remote(5303)再启动本宿主。
5
5
  */
6
6
  import { ref } from 'vue'
7
7
  import { clearAppContext } from '@fulgurjs/federation/runtime'
@@ -0,0 +1,4 @@
1
+ // 精确轨启用方法(把下面片段合入宿主 tsconfig 的 compilerOptions;baseUrl 指向本 tsconfig 所在目录):
2
+ // "paths": { "bridge-react-remote/*": ["src/fulgurjs/types/bridge-react-remote.d/*"] }
3
+ // 说明:零配置轨(bridge-react-remote.d.ts 的 ambient 声明)可解析但导出为宽松类型;
4
+ // 配置 paths 后同形态导入解析到本目录的转发模块,获得远程源码级类型精度。
@@ -0,0 +1,3 @@
1
+ // 自动生成(精确轨):经 tsconfig paths 解析到本文件后获得源码级类型
2
+ export * from "../../../../../react-remote/src/bridge"
3
+ export { default } from "../../../../../react-remote/src/bridge"
@@ -0,0 +1,9 @@
1
+ // 自动生成:fulgurjs-federation dev 类型直连(remote: bridge-react-remote,mode: source)
2
+ // 重新生成:重启 host dev server
3
+
4
+ declare module "bridge-react-remote/bridge" {
5
+ const __fg_default: any
6
+ export default __fg_default
7
+ export const App: any
8
+ export type App = any
9
+ }
@@ -7,23 +7,19 @@
7
7
  | [`remote/`](./remote/) | **Vue 远程**(被消费方) | 5213 | 暴露可点击按钮组件、普通 TS 工具模块、联邦首页与参数详情页 |
8
8
  | [`host/`](./host/) | **Vue 宿主**(消费方) | 5214 | 消费 vue-remote 的组件/模块/页面,提供导航与懒加载 |
9
9
 
10
- - 包管理器统一为 **npm**;插件依赖为 **registry 精确正式包**(`@fulgurjs/federation`,见各 `package.json`),不依赖本仓库源码、monorepo workspace 或父目录 node_modules。
11
- - 把 `host/` 与 `remote/` 复制到**两个互不共享父目录的目录**后,各自 `npm install` 仍可运行。
10
+ - 包管理器为 **pnpm**;复制整个模板目录,包含 workspace 和锁文件。插件使用 registry 正式精确版本。
12
11
 
13
12
  ## 最快开始(从干净拷贝)
14
13
 
15
14
  ```bash
16
- # 终端 1 —— 先启动远程
17
- cd vue/remote
18
- npm install
19
- npm run dev # http://localhost:5213
20
-
21
- # 终端 2 —— 再启动宿主
22
- cd vue/host
23
- npm install
24
- npm run dev # http://localhost:5214
15
+ cd examples/templates/vue-vue # 若已复制出去,进入复制后的模板根
16
+ pnpm install --frozen-lockfile
17
+ pnpm dev # 同时启动远程和宿主
18
+ # http://localhost:5214
25
19
  ```
26
20
 
21
+ 环境要求与 pnpm 版本说明见[模板指南](../README.md)。单独启动用 `pnpm dev:remote`、`pnpm dev:host`,构建整个组合用 `pnpm build`。
22
+
27
23
  打开 <http://localhost:5214/>:
28
24
 
29
25
  - 「首页」里有来自 vue-remote 的**可点击计数按钮**(进入页面才按需加载)。
@@ -44,8 +40,8 @@ npm run dev # http://localhost:5214
44
40
  ## 生产构建与最小 Nginx 部署
45
41
 
46
42
  ```bash
47
- cd vue/remote && npm run build -- --base=/vue-remote/ # 产物 remote/dist/(子路径 base 与部署位置对应)
48
- cd vue/host && npm run build # 产物 host/dist/
43
+ pnpm --dir remote build -- --base=/vue-remote/ # 产物 remote/dist/(子路径 base 与部署位置对应)
44
+ pnpm --dir host build # 产物 host/dist/
49
45
  ```
50
46
 
51
47
  部署形态:宿主部署在站点根 `/`,远程部署在子路径 `/vue-remote/`(与 `host/fulgurjs.config.ts` 的 `prod: '/vue-remote'` 对应)。远程工程的 `vite.config.ts` 已配置 `base` 随 `build` 命令自动切换为 `/vue-remote/`(dev 不变)——Vite 的 preload helper 会把依赖链接转成根绝对路径,远程子路径部署必须带此 base。最小 Nginx 配置(SPA fallback + 联邦入口正确 Content-Type):
@@ -1,19 +1,17 @@
1
1
  # vue-host —— Vue 宿主(fulgurjs 联邦演示)
2
2
 
3
- > **角色:Vue 宿主(消费方)。** 消费 [`../remote/`](../remote/)(vue-remote,端口 5213)暴露的组件、TS 模块与联邦页面;本应用自身不暴露任何模块。
3
+ > **角色:Vue 宿主(消费方)。** 消费 [`../remote/`](../remote)(vue-remote,端口 5213)暴露的组件、TS 模块与联邦页面;本应用自身不暴露任何模块。
4
4
 
5
5
  ## 从干净拷贝运行
6
6
 
7
- 前置:Node ≥ 20.19 与 npm(与本仓库示例验证版本一致即可)。
7
+ 复制整个 `vue-vue/` 模板,在模板根安装依赖后启动本应用:
8
8
 
9
9
  ```bash
10
- # 先启动远程(另一终端):见 ../remote/README.md
11
- cd vue-host # 把本目录复制到任意位置后进入
12
- npm install
13
- npm run dev # http://localhost:5214
10
+ pnpm install --frozen-lockfile
11
+ pnpm --dir host dev
14
12
  ```
15
13
 
16
- 成功画面:导航条含「首页 / 远程首页 / 远程详情 / TS 模块调用」;「远程首页」出现 vue-remote 的标题与可点击计数按钮。
14
+ 宿主需要先启动对应远程;也可以在模板根执行 `pnpm dev` 启动完整组合。环境和完整运行步骤见[组合说明](../README.md)。
17
15
 
18
16
  ## 目录与关键配置
19
17
 
@@ -34,7 +32,7 @@ npm run dev # http://localhost:5214
34
32
  ## 生产构建与部署
35
33
 
36
34
  ```bash
37
- npm run build # dist/
35
+ pnpm run build # dist/
38
36
  ```
39
37
 
40
38
  部署在站点根 `/`(Nginx SPA fallback 见 [组合说明](../README.md#生产构建与最小-nginx-部署))。深链 `/remote/detail/7?tab=basic` 刷新后由 fallback 回退 index.html、插件路由解析恢复同一页面。
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview --port 5214 --strictPort"
10
10
  },
11
11
  "dependencies": {
12
- "@fulgurjs/federation": "5.7.1",
12
+ "@fulgurjs/federation": "5.8.0",
13
13
  "vue": "^3.5.13",
14
14
  "vue-router": "^4.5.0"
15
15
  },
@@ -0,0 +1,4 @@
1
+ // 自动生成(精确轨):.vue expose 为宽松形态(精确类型需宿主 vue-tsc/shim)
2
+ import type { DefineComponent } from 'vue'
3
+ declare const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>
4
+ export default component
@@ -0,0 +1,4 @@
1
+ // 精确轨启用方法(把下面片段合入宿主 tsconfig 的 compilerOptions;baseUrl 指向本 tsconfig 所在目录):
2
+ // "paths": { "vue-remote/*": ["src/fulgurjs/types/vue-remote.d/*"] }
3
+ // 说明:零配置轨(vue-remote.d.ts 的 ambient 声明)可解析但导出为宽松类型;
4
+ // 配置 paths 后同形态导入解析到本目录的转发模块,获得远程源码级类型精度。
@@ -0,0 +1,4 @@
1
+ // 自动生成(精确轨):.vue expose 为宽松形态(精确类型需宿主 vue-tsc/shim)
2
+ import type { DefineComponent } from 'vue'
3
+ declare const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>
4
+ export default component
@@ -0,0 +1,4 @@
1
+ // 自动生成(精确轨):.vue expose 为宽松形态(精确类型需宿主 vue-tsc/shim)
2
+ import type { DefineComponent } from 'vue'
3
+ declare const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>
4
+ export default component
@@ -0,0 +1,2 @@
1
+ // 自动生成(精确轨):经 tsconfig paths 解析到本文件后获得源码级类型
2
+ export * from "../../../../../remote/src/exposes/utils"
@@ -0,0 +1,29 @@
1
+ // 自动生成:fulgurjs-federation dev 类型直连(remote: vue-remote,mode: source)
2
+ // 重新生成:重启 host dev server
3
+
4
+ declare module "vue-remote/ClickButton" {
5
+ import type { DefineComponent } from 'vue'
6
+ const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>
7
+ export default component
8
+ }
9
+
10
+ declare module "vue-remote/utils" {
11
+ export const sumNumbers: any
12
+ export type sumNumbers = any
13
+ export const formatPrice: any
14
+ export type formatPrice = any
15
+ export const DEMO_ANSWER: any
16
+ export type DEMO_ANSWER = any
17
+ }
18
+
19
+ declare module "vue-remote/pages/HomePage" {
20
+ import type { DefineComponent } from 'vue'
21
+ const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>
22
+ export default component
23
+ }
24
+
25
+ declare module "vue-remote/pages/DetailPage" {
26
+ import type { DefineComponent } from 'vue'
27
+ const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>
28
+ export default component
29
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vite'
2
+ import vue from '@vitejs/plugin-vue'
3
+ import { federation } from '@fulgurjs/federation'
4
+ import fulgurjsConfig from './fulgurjs.config.ts'
5
+
6
+ export default defineConfig({
7
+ plugins: [vue(), federation(fulgurjsConfig)],
8
+ })
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "fulgurjs-template-vue-vue",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "scripts": {
6
+ "dev:remote": "pnpm --dir remote dev",
7
+ "dev:host": "pnpm --dir host dev",
8
+ "dev": "node scripts/dev.mjs",
9
+ "build": "pnpm --dir remote build && pnpm --dir host build"
10
+ }
11
+ }