@fulgurjs/federation 5.1.3 → 5.2.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 (88) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.en.md +7 -5
  3. package/README.md +14 -12
  4. package/dist/context.cjs +2 -2
  5. package/dist/context.js +2 -2
  6. package/dist/index.cjs +141 -48
  7. package/dist/index.js +141 -48
  8. package/dist/react-adapter.cjs +32 -1
  9. package/dist/react-adapter.d.cts +1 -1
  10. package/dist/react-adapter.d.ts +1 -1
  11. package/dist/react-adapter.js +32 -1
  12. package/dist/react.d.ts +2 -2
  13. package/dist/runtime-entry.d.ts +2 -2
  14. package/dist/runtime.js +7 -7
  15. package/dist/vue-adapter.cjs +99 -15
  16. package/dist/vue-adapter.d.cts +1 -1
  17. package/dist/vue-adapter.d.ts +1 -1
  18. package/dist/vue-adapter.js +100 -16
  19. package/examples/README.en.md +47 -0
  20. package/examples/README.md +40 -18
  21. package/examples/react/README.md +83 -0
  22. package/examples/react/host/README.md +49 -0
  23. package/examples/react/host/fulgurjs.config.ts +31 -0
  24. package/examples/{react-remote → react/host}/index.html +2 -1
  25. package/examples/react/host/package-lock.json +2381 -0
  26. package/examples/react/host/package.json +24 -0
  27. package/examples/react/host/src/App.tsx +19 -0
  28. package/examples/react/host/src/main.tsx +33 -0
  29. package/examples/react/host/src/pages/UtilsDemo.tsx +32 -0
  30. package/examples/react/host/src/remotePages.tsx +16 -0
  31. package/examples/{react-remote → react/host}/tsconfig.json +2 -3
  32. package/examples/{react-remote → react/host}/vite.config.ts +2 -2
  33. package/examples/react/remote/README.md +47 -0
  34. package/examples/react/remote/fulgurjs.config.ts +20 -0
  35. package/examples/{react-host → react/remote}/index.html +2 -1
  36. package/examples/react/remote/package-lock.json +2323 -0
  37. package/examples/react/remote/package.json +23 -0
  38. package/examples/react/remote/src/App.tsx +16 -0
  39. package/examples/react/remote/src/exposes/ClickButton.tsx +15 -0
  40. package/examples/react/remote/src/exposes/pages/DetailPage.tsx +10 -0
  41. package/examples/react/remote/src/exposes/pages/HomePage.tsx +12 -0
  42. package/examples/react/remote/src/exposes/utils.ts +10 -0
  43. package/examples/react/remote/src/main.tsx +11 -0
  44. package/examples/{react-host → react/remote}/tsconfig.json +3 -4
  45. package/examples/{react-host → react/remote}/vite.config.ts +2 -2
  46. package/examples/vue/README.md +85 -0
  47. package/examples/vue/host/README.md +50 -0
  48. package/examples/vue/host/fulgurjs.config.ts +30 -0
  49. package/examples/vue/host/index.html +12 -0
  50. package/examples/vue/host/package-lock.json +1855 -0
  51. package/examples/vue/host/package.json +21 -0
  52. package/examples/vue/host/src/App.vue +12 -0
  53. package/examples/vue/host/src/main.ts +44 -0
  54. package/examples/vue/host/src/pages/HomePage.vue +16 -0
  55. package/examples/vue/host/src/pages/UtilsDemo.vue +45 -0
  56. package/examples/vue/host/tsconfig.json +13 -0
  57. package/examples/vue/host/vite.config.ts +8 -0
  58. package/examples/vue/remote/README.md +47 -0
  59. package/examples/vue/remote/fulgurjs.config.ts +20 -0
  60. package/examples/vue/remote/index.html +12 -0
  61. package/examples/vue/remote/package-lock.json +1833 -0
  62. package/examples/vue/remote/package.json +20 -0
  63. package/examples/vue/remote/src/App.vue +16 -0
  64. package/examples/vue/remote/src/exposes/ClickButton.vue +16 -0
  65. package/examples/vue/remote/src/exposes/pages/DetailPage.vue +14 -0
  66. package/examples/vue/remote/src/exposes/pages/HomePage.vue +11 -0
  67. package/examples/vue/remote/src/exposes/utils.ts +10 -0
  68. package/examples/vue/remote/src/main.ts +6 -0
  69. package/examples/vue/remote/tsconfig.json +13 -0
  70. package/examples/vue/remote/vite.config.ts +8 -0
  71. package/package.json +2 -2
  72. package/examples/host/fulgurjs.config.ts +0 -26
  73. package/examples/react-host/README.md +0 -28
  74. package/examples/react-host/fulgurjs.config.ts +0 -19
  75. package/examples/react-host/package.json +0 -23
  76. package/examples/react-host/src/App.tsx +0 -66
  77. package/examples/react-host/src/federation/pages.data.ts +0 -21
  78. package/examples/react-host/src/main.tsx +0 -8
  79. package/examples/react-remote/fulgurjs.config.ts +0 -17
  80. package/examples/react-remote/package.json +0 -22
  81. package/examples/react-remote/src/Button.tsx +0 -15
  82. package/examples/react-remote/src/main.tsx +0 -6
  83. package/examples/react-remote/src/pages/Detail.tsx +0 -10
  84. package/examples/react-remote/src/pages/Home.tsx +0 -14
  85. package/examples/react-remote/src/utils.ts +0 -3
  86. package/examples/remote-a/fulgurjs.config.ts +0 -24
  87. package/examples/remote-a/src/views/Detail.vue +0 -3
  88. package/examples/remote-a/src/views/Home.vue +0 -3
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "fulgurjs-demo-react-remote",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite --port 5203 --strictPort",
8
+ "build": "vite build",
9
+ "preview": "vite preview --port 5203 --strictPort"
10
+ },
11
+ "dependencies": {
12
+ "@fulgurjs/federation": "file:../../../../work/fulgurjs-federation-5.2.0.tgz",
13
+ "react": "^19.1.0",
14
+ "react-dom": "^19.1.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^19.1.0",
18
+ "@types/react-dom": "^19.1.0",
19
+ "@vitejs/plugin-react": "^5.0.0",
20
+ "typescript": "^5.8.0",
21
+ "vite": "^6.3.5"
22
+ }
23
+ }
@@ -0,0 +1,16 @@
1
+ import ClickButton from './exposes/ClickButton'
2
+
3
+ /** 独立运行壳:联邦消费方按 exposes 加载下列模块 */
4
+ export default function App() {
5
+ return (
6
+ <div style={{ fontFamily: 'sans-serif', padding: 16 }}>
7
+ <h1>react-remote 独立运行</h1>
8
+ <ul>
9
+ <li>./ClickButton —— 可点击计数按钮组件</li>
10
+ <li>./utils —— 普通 TS 工具模块</li>
11
+ <li>./pages/HomePage / ./pages/DetailPage —— 联邦页面</li>
12
+ </ul>
13
+ <ClickButton />
14
+ </div>
15
+ )
16
+ }
@@ -0,0 +1,15 @@
1
+ import { useState } from 'react'
2
+
3
+ /** 可点击计数按钮:本地 state 保存在远程组件内部(宿主消费时运行在宿主页面的 React 上) */
4
+ export default function ClickButton() {
5
+ const [count, setCount] = useState(0)
6
+ return (
7
+ <button
8
+ data-testid="demo-remote-button"
9
+ style={{ padding: '8px 16px', border: 'none', borderRadius: 6, background: '#1677ff', color: '#fff', cursor: 'pointer' }}
10
+ onClick={() => setCount((c) => c + 1)}
11
+ >
12
+ 远程按钮(点击了 {count} 次)
13
+ </button>
14
+ )
15
+ }
@@ -0,0 +1,10 @@
1
+ /** 联邦参数页:宿主路由的 params + query 作为 props 传入 */
2
+ export default function DetailPage({ id, tab }: { id?: string; tab?: string }) {
3
+ return (
4
+ <div data-testid="demo-remote-detail">
5
+ <h3>react-remote / 详情页</h3>
6
+ <p data-testid="demo-detail-id">路由参数 id:{id ?? '(无)'}</p>
7
+ <p data-testid="demo-detail-tab">query 参数 tab:{tab ?? '(无)'}</p>
8
+ </div>
9
+ )
10
+ }
@@ -0,0 +1,12 @@
1
+ import ClickButton from '../ClickButton'
2
+
3
+ /** 联邦页面:渲染在宿主的路由出口内 */
4
+ export default function HomePage() {
5
+ return (
6
+ <div data-testid="demo-remote-home">
7
+ <h3>react-remote / 首页</h3>
8
+ <p>这是由 react-remote 暴露的联邦页面。</p>
9
+ <ClickButton />
10
+ </div>
11
+ )
12
+ }
@@ -0,0 +1,10 @@
1
+ /** 普通 TS 工具模块:演示跨应用函数/常量消费(不含任何组件) */
2
+ export const DEMO_ANSWER = 42
3
+
4
+ export function sumNumbers(...numbers: number[]): number {
5
+ return numbers.reduce((acc, n) => acc + n, 0)
6
+ }
7
+
8
+ export function formatPrice(yuan: number): string {
9
+ return `¥${yuan.toFixed(2)}`
10
+ }
@@ -0,0 +1,11 @@
1
+ import { StrictMode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import App from './App'
4
+
5
+ // 独立运行入口:单独开发/调试远程自身时使用。
6
+ // 被宿主消费时走的是 fulgurjs-remoteEntry.js 容器入口,与本文件无关。
7
+ createRoot(document.getElementById('root')!).render(
8
+ <StrictMode>
9
+ <App />
10
+ </StrictMode>,
11
+ )
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2022",
4
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
4
  "module": "ESNext",
6
5
  "moduleResolution": "bundler",
7
- "jsx": "react-jsx",
8
6
  "strict": true,
7
+ "jsx": "react-jsx",
9
8
  "skipLibCheck": true,
10
9
  "noEmit": true,
11
- "isolatedModules": true
10
+ "types": ["vite/client"]
12
11
  },
13
- "include": ["src", "src/fulgurjs/types", "fulgurjs.config.ts", "vite.config.ts"]
12
+ "include": ["src", "fulgurjs.config.ts", "vite.config.ts"]
14
13
  }
@@ -1,7 +1,7 @@
1
1
  import { defineConfig } from 'vite'
2
2
  import react from '@vitejs/plugin-react'
3
- import federation from '@fulgurjs/federation'
4
- import fulgurjsConfig from './fulgurjs.config'
3
+ import { federation } from '@fulgurjs/federation'
4
+ import fulgurjsConfig from './fulgurjs.config.ts'
5
5
 
6
6
  export default defineConfig({
7
7
  plugins: [react(), federation(fulgurjsConfig)],
@@ -0,0 +1,85 @@
1
+ # Vue 联邦示例:宿主 + 远程(可直接复制运行)
2
+
3
+ 本目录是一对完整、可独立安装运行的 Vue 3 模块联邦演示:
4
+
5
+ | 目录 | 角色 | 端口 | 说明 |
6
+ | --- | --- | --- | --- |
7
+ | [`remote/`](./remote/) | **Vue 远程**(被消费方) | 5213 | 暴露可点击按钮组件、普通 TS 工具模块、联邦首页与参数详情页 |
8
+ | [`host/`](./host/) | **Vue 宿主**(消费方) | 5214 | 消费 vue-remote 的组件/模块/页面,提供导航与懒加载 |
9
+
10
+ - 包管理器统一为 **npm**;插件依赖为 **registry 精确正式包**(`@fulgurjs/federation`,见各 `package.json`),不依赖本仓库源码、monorepo workspace 或父目录 node_modules。
11
+ - 把 `host/` 与 `remote/` 复制到**两个互不共享父目录的目录**后,各自 `npm install` 仍可运行。
12
+
13
+ ## 最快开始(从干净拷贝)
14
+
15
+ ```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
25
+ ```
26
+
27
+ 打开 <http://localhost:5214/>:
28
+
29
+ - 「首页」里有来自 vue-remote 的**可点击计数按钮**(进入页面才按需加载)。
30
+ - 「远程首页 / 远程详情」是 vue-remote 暴露的**联邦页面**,渲染在宿主路由出口内;详情页演示真实路由参数(`/remote/detail/7?tab=basic`)。
31
+ - 「TS 模块调用」演示宿主调用 vue-remote 暴露的普通 TS 模块(`loadRemote` + 显式调用导出)。
32
+ - 停掉远程 dev server 再刷新宿主页面 → 插件默认错误占位出现,提供**「重试加载」**(同页恢复)与**「刷新页面重试」**(整页恢复)两个操作;重启远程后点击即可恢复业务。
33
+
34
+ ## 演示的功能点
35
+
36
+ | 功能 | 位置 |
37
+ | --- | --- |
38
+ | 远程可点击组件(计数、本地状态在远程组件内) | `remote/src/exposes/ClickButton.vue`,宿主首页消费 |
39
+ | 普通 TS 模块调用 | `remote/src/exposes/utils.ts`,`host/src/pages/UtilsDemo.vue` |
40
+ | 联邦页面(远程首页 / 带参数详情页) | `remote/src/exposes/pages/`,页面表见 `host/fulgurjs.config.ts` |
41
+ | 宿主导航 + 懒加载(不批量预取) | `host/src/App.vue` + `host/src/main.ts`(路由级按需加载) |
42
+ | 默认加载/错误/恢复占位 | 插件内置(`remoteComponent` / `createHostPages`),示例不自建错误组件 |
43
+
44
+ ## 生产构建与最小 Nginx 部署
45
+
46
+ ```bash
47
+ cd vue/remote && npm run build -- --base=/vue-remote/ # 产物 remote/dist/(子路径 base 与部署位置对应)
48
+ cd vue/host && npm run build # 产物 host/dist/
49
+ ```
50
+
51
+ 部署形态:宿主部署在站点根 `/`,远程部署在子路径 `/vue-remote/`(与 `host/fulgurjs.config.ts` 的 `prod: '/vue-remote'` 对应)。远程构建产物内部的 chunk 引用是相对路径,天然适配子路径。最小 Nginx 配置(SPA fallback + 联邦入口正确 Content-Type):
52
+
53
+ ```nginx
54
+ server {
55
+ listen 8080;
56
+
57
+ # 宿主(站点根)
58
+ root /srv/vue-demo/host;
59
+ index index.html;
60
+
61
+ # 远程静态资源(子路径)
62
+ location /vue-remote/ {
63
+ alias /srv/vue-demo/remote/;
64
+ try_files $uri $uri/ =404;
65
+ }
66
+
67
+ # 宿主 SPA fallback:深链刷新(如 /remote/detail/7)回退到 index.html
68
+ location / {
69
+ try_files $uri /index.html;
70
+ }
71
+ }
72
+ ```
73
+
74
+ 部署后访问 `http://<host>:8080/`,深链 `http://<host>:8080/remote/detail/7?tab=basic` 直接刷新也能到达同一页面(Nginx fallback → 宿主 index.html → 插件路由解析)。
75
+
76
+ ## HMR 边界(dev)
77
+
78
+ - 远程 `.vue` 组件修改(模板/样式/兼容的 script)会经远程 dev server 自动热更新到**正在显示的宿主页面**,组件本地状态保留,无整页刷新。
79
+ - 远程普通 TS 模块修改同样自动传播到引用它的组件边界。
80
+ - 不兼容的导出结构变化按 Vite/Vue 标准触发整页刷新(full-reload)——这是框架标准行为,不是「任意改动都保活」。
81
+
82
+ ## examples 与 fixtures 的区别
83
+
84
+ `examples/` 面向**使用者**:拷贝、安装 registry 正式包、独立运行。
85
+ 仓库根的 `fixtures/` 是**插件内部回归夹具**(源码 `link:` 到插件工作区),不要当作使用模板。
@@ -0,0 +1,50 @@
1
+ # vue-host —— Vue 宿主(fulgurjs 联邦演示)
2
+
3
+ > **角色:Vue 宿主(消费方)。** 消费 [`../remote/`](../remote/)(vue-remote,端口 5213)暴露的组件、TS 模块与联邦页面;本应用自身不暴露任何模块。
4
+
5
+ ## 从干净拷贝运行
6
+
7
+ 前置:Node ≥ 20.19 与 npm(与本仓库示例验证版本一致即可)。
8
+
9
+ ```bash
10
+ # 先启动远程(另一终端):见 ../remote/README.md
11
+ cd vue-host # 把本目录复制到任意位置后进入
12
+ npm install
13
+ npm run dev # http://localhost:5214
14
+ ```
15
+
16
+ 成功画面:导航条含「首页 / 远程首页 / 远程详情 / TS 模块调用」;「远程首页」出现 vue-remote 的标题与可点击计数按钮。
17
+
18
+ ## 目录与关键配置
19
+
20
+ | 文件 | 职责 |
21
+ | --- | --- |
22
+ | `fulgurjs.config.ts` | **联邦唯一声明**:remotes 地址(dev/prod)、页面表 `pages`、前缀归属 `remotePrefixes`。改远程地址只动这里 |
23
+ | `vite.config.ts` | 标准 Vite 配置,`federation(fulgurjsConfig)` 挂载插件 |
24
+ | `src/main.ts` | 路由 + `createHostPages({ pages, remotePrefixes })`;远程页面用 `hostPages.component('<远程名>/<expose 键>')` |
25
+ | `src/pages/HomePage.vue` | `remoteComponent('vue-remote/ClickButton')` 消费单个远程组件 |
26
+ | `src/pages/UtilsDemo.vue` | `loadRemote('vue-remote/utils')` 调用普通 TS 模块 |
27
+
28
+ ## API 职责速查
29
+
30
+ - `remoteComponent(spec)`:单个远程组件;首次渲染才加载;失败时插件内置中文错误占位(错误码 + 修法 + **重试加载** + **刷新页面重试**)。
31
+ - `createHostPages({ pages, remotePrefixes })`:页面表驱动;`component(spec)` 返回异步页面组件(同 spec 复用);加载/错误占位由插件提供。
32
+ - `loadRemote(spec)`:加载任意 expose(组件或纯 TS 模块),返回模块命名空间。
33
+
34
+ ## 生产构建与部署
35
+
36
+ ```bash
37
+ npm run build # dist/
38
+ ```
39
+
40
+ 部署在站点根 `/`(Nginx SPA fallback 见 [组合说明](../README.md#生产构建与最小-nginx-部署))。深链 `/remote/detail/7?tab=basic` 刷新后由 fallback 回退 index.html、插件路由解析恢复同一页面。
41
+
42
+ ## 恢复操作(故障演练)
43
+
44
+ 1. 停掉 vue-remote(Ctrl-C 远程终端)。
45
+ 2. 刷新宿主页面并进入任一远程页面 → 插件默认错误占位(远程组件加载失败 + 错误码)。
46
+ 3. 重启 vue-remote → 点占位上的「重试加载」同页恢复;若浏览器已缓存失败的模块(如远程静态子依赖曾失败),点「刷新页面重试」整页恢复(保留当前地址)。
47
+
48
+ ## HMR
49
+
50
+ vue-remote 的组件/TS 模块修改会自动热更新到本宿主正在显示的页面(无需手动刷新);不兼容改动按 Vite/Vue 标准触发 full-reload。
@@ -0,0 +1,30 @@
1
+ import type { FederationOptions, PageRouteLike } from '@fulgurjs/federation'
2
+
3
+ /**
4
+ * 宿主端联邦配置(唯一需要维护的联邦声明文件)。
5
+ * - remotes:改远程地址只动这里;dev 与生产可以分别指定。
6
+ * - hostPages:页面表 + 路由前缀归属,浏览器侧 createHostPages 与 CLI check-pages 共用。
7
+ */
8
+ export default {
9
+ name: 'vue-host',
10
+ remotes: {
11
+ 'vue-remote': {
12
+ dev: 'http://localhost:5213',
13
+ prod: '/vue-remote',
14
+ },
15
+ },
16
+ shared: {
17
+ vue: { singleton: true },
18
+ },
19
+ } satisfies FederationOptions
20
+
21
+ /** 页面表:URL 路由 → 远程 expose 的映射(spec = 远程名 + exposes 键) */
22
+ export const pages: PageRouteLike[] = [
23
+ { route: '/remote/home', spec: 'pages/HomePage', name: 'RemoteHome', title: '远程首页' },
24
+ { route: '/remote/detail/:id', spec: 'pages/DetailPage', name: 'RemoteDetail', title: '远程详情' },
25
+ ]
26
+
27
+ /** 路由前缀 → 远程归属(最长前缀匹配) */
28
+ export const remotePrefixes: Record<string, string> = {
29
+ '/remote': 'vue-remote',
30
+ }
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>vue-host(fulgurjs 演示宿主)</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.ts"></script>
11
+ </body>
12
+ </html>