@fulgurjs/federation 5.0.3 → 5.1.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.
- package/CHANGELOG.md +13 -0
- package/DESIGN.md +11 -0
- package/README.en.md +441 -0
- package/README.md +120 -5
- package/dist/chunk-4PLNAYZX.js +84 -0
- package/dist/cli.js +4 -1
- package/dist/host-pages-core-BFxp-IOj.d.cts +37 -0
- package/dist/host-pages-core-DLfMeDrO.d.ts +37 -0
- package/dist/index.cjs +137 -26
- package/dist/index.js +137 -26
- package/dist/react-adapter.cjs +518 -0
- package/dist/react-adapter.d.cts +117 -0
- package/dist/react-adapter.d.ts +117 -0
- package/dist/react-adapter.js +292 -0
- package/dist/react.d.ts +442 -0
- package/dist/react.js +10 -0
- package/dist/runtime-entry.d.ts +29 -17
- package/dist/runtime.js +13 -13
- package/dist/vue-adapter.cjs +66 -50
- package/dist/vue-adapter.d.cts +4 -25
- package/dist/vue-adapter.d.ts +4 -25
- package/dist/vue-adapter.js +14 -66
- package/examples/README.md +5 -0
- package/examples/react-host/README.md +28 -0
- package/examples/react-host/fulgurjs.config.ts +19 -0
- package/examples/react-host/index.html +11 -0
- package/examples/react-host/package.json +23 -0
- package/examples/react-host/src/App.tsx +66 -0
- package/examples/react-host/src/federation/pages.data.ts +19 -0
- package/examples/react-host/src/main.tsx +8 -0
- package/examples/react-host/tsconfig.json +14 -0
- package/examples/react-host/vite.config.ts +8 -0
- package/examples/react-remote/fulgurjs.config.ts +17 -0
- package/examples/react-remote/index.html +11 -0
- package/examples/react-remote/package.json +22 -0
- package/examples/react-remote/src/Button.tsx +15 -0
- package/examples/react-remote/src/main.tsx +6 -0
- package/examples/react-remote/src/pages/Detail.tsx +10 -0
- package/examples/react-remote/src/pages/Home.tsx +14 -0
- package/examples/react-remote/src/utils.ts +3 -0
- package/examples/react-remote/tsconfig.json +14 -0
- package/examples/react-remote/vite.config.ts +8 -0
- package/package.json +30 -3
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-host:一个文件看清 React 宿主的联邦用法。
|
|
3
|
+
* ① 每个应用根目录一份 fulgurjs.config.ts(纯数据);vite.config.ts 调 federation(fulgurjsConfig)
|
|
4
|
+
* ② React 应用统一从 '@fulgurjs/federation/react' 导入(通用运行时 + React 适配 API)
|
|
5
|
+
* ③ remoteComponent 工厂放模块顶层(首次渲染才加载);页面用 createReactHostPages + component(spec)
|
|
6
|
+
*/
|
|
7
|
+
import { Link, Route, Routes, useParams, useSearchParams } from 'react-router-dom'
|
|
8
|
+
import {
|
|
9
|
+
createReactHostPages,
|
|
10
|
+
remoteComponent,
|
|
11
|
+
remoteSchema,
|
|
12
|
+
useLoadRemote,
|
|
13
|
+
} from '@fulgurjs/federation/react'
|
|
14
|
+
import { pages, remotePrefixes } from './federation/pages.data'
|
|
15
|
+
|
|
16
|
+
// 页面表(纯数据 + dev schema;R1–R5 校验与 Vue 完全一致)
|
|
17
|
+
const hp = createReactHostPages({ pages, remotePrefixes, schema: remoteSchema })
|
|
18
|
+
|
|
19
|
+
// 普通远程组件:模块顶层创建,不能在 render 内重复调用工厂
|
|
20
|
+
const RemoteButton = remoteComponent<{ label: string; onClick?: () => void }>('remote-react/Button', {
|
|
21
|
+
fallback: <p>正在加载远程按钮…</p>,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// 页面组件:与 Vue 相同动词 component(spec);路由层用 element 渲染
|
|
25
|
+
const RemoteHome = hp.component('remote-react/pages/home')
|
|
26
|
+
const RemoteDetail = hp.component<{ id: string; tab?: string }>('remote-react/pages/detail')
|
|
27
|
+
|
|
28
|
+
/** 普通远程模块:useLoadRemote(data/error/loading/reload;错误无默认占位,由宿主决定 UI) */
|
|
29
|
+
function UtilsPanel() {
|
|
30
|
+
type Utils = { formatMoney(v: number, currency?: string): string }
|
|
31
|
+
const { data, error, loading, reload } = useLoadRemote<Utils>('remote-react/utils')
|
|
32
|
+
if (loading) return <p>utils 加载中…</p>
|
|
33
|
+
if (error) return <button onClick={() => void reload()}>utils 加载失败,重试</button>
|
|
34
|
+
return (
|
|
35
|
+
<p>
|
|
36
|
+
12.5 → {data?.formatMoney(12.5)}(<button onClick={() => void reload()}>reload</button>)
|
|
37
|
+
</p>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function DetailRoute() {
|
|
42
|
+
const { id } = useParams()
|
|
43
|
+
const [sp] = useSearchParams()
|
|
44
|
+
return <RemoteDetail id={id ?? ''} tab={sp.get('tab') ?? undefined} />
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default function App() {
|
|
48
|
+
return (
|
|
49
|
+
<div style={{ fontFamily: 'sans-serif', padding: 16 }}>
|
|
50
|
+
<h1>react-host(fulgurjs example)</h1>
|
|
51
|
+
<nav>
|
|
52
|
+
<Link to="/">首页</Link> · <Link to="/remote-react/home">远程首页</Link> ·{' '}
|
|
53
|
+
<Link to="/remote-react/detail/42?tab=basic">远程参数页</Link>
|
|
54
|
+
</nav>
|
|
55
|
+
<Routes>
|
|
56
|
+
<Route path="/" element={<main>
|
|
57
|
+
<p>宿主首页(远程组件按需加载)</p>
|
|
58
|
+
<RemoteButton label="远程按钮" onClick={() => console.log('clicked')} />
|
|
59
|
+
<UtilsPanel />
|
|
60
|
+
</main>} />
|
|
61
|
+
<Route path="/remote-react/home" element={<RemoteHome />} />
|
|
62
|
+
<Route path="/remote-react/detail/:id" element={<DetailRoute />} />
|
|
63
|
+
</Routes>
|
|
64
|
+
</div>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 页面表数据(纯数据:不 import React/路由库/浏览器对象——CLI 与浏览器适配器共用)。
|
|
3
|
+
* spec 缺省推导 = 去首段(远程前缀)+ 剥 :参数 段;带参路由建议显式 spec。
|
|
4
|
+
*/
|
|
5
|
+
export interface PageRecord {
|
|
6
|
+
route: string
|
|
7
|
+
spec?: string
|
|
8
|
+
name?: string
|
|
9
|
+
title?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const pages: PageRecord[] = [
|
|
13
|
+
{ route: '/remote-react/home', spec: 'pages/home', name: 'RemoteHome' },
|
|
14
|
+
{ route: '/remote-react/detail/:id', spec: 'pages/detail', name: 'RemoteDetail' },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
export const remotePrefixes: Record<string, string> = {
|
|
18
|
+
'/remote-react': 'remote-react',
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createElement, StrictMode } from 'react'
|
|
2
|
+
import { createRoot } from 'react-dom/client'
|
|
3
|
+
import { BrowserRouter } from 'react-router-dom'
|
|
4
|
+
import App from './App'
|
|
5
|
+
|
|
6
|
+
createRoot(document.getElementById('root')!).render(
|
|
7
|
+
createElement(StrictMode, null, createElement(BrowserRouter, null, createElement(App))),
|
|
8
|
+
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"isolatedModules": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src", "src/fulgurjs/types", "fulgurjs.config.ts", "vite.config.ts"]
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FederationOptions } from '@fulgurjs/federation'
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
name: 'remote-react',
|
|
5
|
+
exposes: {
|
|
6
|
+
'./Button': './src/Button.tsx',
|
|
7
|
+
'./utils': './src/utils.ts',
|
|
8
|
+
'./pages/home': './src/pages/Home.tsx',
|
|
9
|
+
'./pages/detail': './src/pages/Detail.tsx',
|
|
10
|
+
},
|
|
11
|
+
// 有初始化需求才添加(应用级 setup 一次 + 会话级 onSession 按宿主 sessionKey 去重):
|
|
12
|
+
// setup: './src/fulgurjs/setup.ts',
|
|
13
|
+
shared: {
|
|
14
|
+
react: { singleton: true },
|
|
15
|
+
'react-dom': { singleton: true },
|
|
16
|
+
},
|
|
17
|
+
} satisfies FederationOptions
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fulgurjs-example-react-remote",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite --port 5203 --strictPort",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview --port 5203 --strictPort"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"react": "^19.3.0",
|
|
12
|
+
"react-dom": "^19.3.0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@fulgurjs/federation": "^5.1.0",
|
|
16
|
+
"@types/react": "^19.3.0",
|
|
17
|
+
"@types/react-dom": "^19.3.0",
|
|
18
|
+
"@vitejs/plugin-react": "^5.2.0",
|
|
19
|
+
"typescript": "^5.8.0",
|
|
20
|
+
"vite": "^6.3.5"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
|
|
3
|
+
export interface ButtonProps {
|
|
4
|
+
label: string
|
|
5
|
+
onClick?: () => void
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function Button({ label, onClick }: ButtonProps) {
|
|
9
|
+
const [count, setCount] = useState(0)
|
|
10
|
+
return (
|
|
11
|
+
<button type="button" onClick={() => { setCount((c) => c + 1); onClick?.() }}>
|
|
12
|
+
{label}:已点击 {count} 次
|
|
13
|
+
</button>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
export default function Home() {
|
|
4
|
+
const [now, setNow] = useState('')
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
setNow(new Date().toISOString().slice(0, 19))
|
|
7
|
+
}, [])
|
|
8
|
+
return (
|
|
9
|
+
<section>
|
|
10
|
+
<h2>remote-react / Home</h2>
|
|
11
|
+
<p>mounted at {now}</p>
|
|
12
|
+
</section>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"isolatedModules": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src", "fulgurjs.config.ts", "vite.config.ts"]
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fulgurjs/federation",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vite Module Federation with full Webpack MF parity. Dev & production, no compromise.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"types": "./dist/runtime-entry.d.ts",
|
|
18
18
|
"import": "./dist/runtime-entry.js"
|
|
19
19
|
},
|
|
20
|
+
"./react": {
|
|
21
|
+
"types": "./dist/react.d.ts",
|
|
22
|
+
"import": "./dist/react.js"
|
|
23
|
+
},
|
|
20
24
|
"./package.json": "./package.json",
|
|
21
25
|
"./internal/context.js": {
|
|
22
26
|
"types": "./dist/context.d.ts",
|
|
@@ -32,18 +36,27 @@
|
|
|
32
36
|
"types": "./dist/vue-adapter.d.ts",
|
|
33
37
|
"import": "./dist/vue-adapter.js",
|
|
34
38
|
"require": "./dist/vue-adapter.cjs"
|
|
39
|
+
},
|
|
40
|
+
"./internal/react-adapter.js": {
|
|
41
|
+
"types": "./dist/react-adapter.d.ts",
|
|
42
|
+
"import": "./dist/react-adapter.js",
|
|
43
|
+
"require": "./dist/react-adapter.cjs"
|
|
35
44
|
}
|
|
36
45
|
},
|
|
37
46
|
"typesVersions": {
|
|
38
47
|
"*": {
|
|
39
48
|
"runtime": [
|
|
40
49
|
"dist/runtime-entry.d.ts"
|
|
50
|
+
],
|
|
51
|
+
"react": [
|
|
52
|
+
"dist/react.d.ts"
|
|
41
53
|
]
|
|
42
54
|
}
|
|
43
55
|
},
|
|
44
56
|
"files": [
|
|
45
57
|
"dist",
|
|
46
58
|
"README.md",
|
|
59
|
+
"README.en.md",
|
|
47
60
|
"LICENSE",
|
|
48
61
|
"CHANGELOG.md",
|
|
49
62
|
"DESIGN.md",
|
|
@@ -54,7 +67,7 @@
|
|
|
54
67
|
"docs/P5-vite7-8兼容矩阵.md"
|
|
55
68
|
],
|
|
56
69
|
"scripts": {
|
|
57
|
-
"build": "cp ../../README.md README.md && mkdir -p docs && cp ../../docs/迁移指南.md ../../docs/webpack-mf-对照与缺口.md ../../docs/沙箱边界审计.md ../../docs/P5-vite7-8兼容矩阵.md docs/ && cp ../../CHANGELOG.md CHANGELOG.md && cp ../../DESIGN.md DESIGN.md && rm -rf examples && cp -r ../../examples examples && esbuild src/runtime/index.ts --bundle --format=esm --target=es2022 --minify --outfile=dist/runtime.js && node scripts/gen-runtime.mjs && tsup src/index.ts src/pages.ts src/vue-adapter.ts src/context.ts --format esm,cjs --dts --external vite --target node18 --clean && tsup src/runtime-entry.ts --format esm --dts --external vite,vue --target node18 && esbuild src/cli.ts --bundle --format=esm --target=node18 --platform=node --outfile=dist/cli.js && esbuild src/runtime/index.ts --bundle --format=esm --target=es2022 --minify --outfile=dist/runtime.js && node scripts/gen-runtime-entry.mjs && node scripts/check-gzip.mjs && node scripts/check-manual-codes.mjs",
|
|
70
|
+
"build": "cp ../../README.md README.md && cp ../../README.en.md README.en.md && mkdir -p docs && cp ../../docs/迁移指南.md ../../docs/webpack-mf-对照与缺口.md ../../docs/沙箱边界审计.md ../../docs/P5-vite7-8兼容矩阵.md docs/ && cp ../../CHANGELOG.md CHANGELOG.md && cp ../../DESIGN.md DESIGN.md && rm -rf examples && cp -r ../../examples examples && esbuild src/runtime/index.ts --bundle --format=esm --target=es2022 --minify --outfile=dist/runtime.js && node scripts/gen-runtime.mjs && tsup src/index.ts src/pages.ts src/vue-adapter.ts src/react-adapter.ts src/context.ts --format esm,cjs --dts --external vite --target node18 --clean && tsup src/runtime-entry.ts --format esm --dts --external vite,vue --target node18 && tsup src/react.ts --format esm --dts --external vite,react --target node18 && esbuild src/cli.ts --bundle --format=esm --target=node18 --platform=node --outfile=dist/cli.js && esbuild src/runtime/index.ts --bundle --format=esm --target=es2022 --minify --outfile=dist/runtime.js && node scripts/gen-runtime-entry.mjs && node scripts/check-gzip.mjs && node scripts/check-manual-codes.mjs",
|
|
58
71
|
"dev": "tsup --watch",
|
|
59
72
|
"test": "vitest run",
|
|
60
73
|
"typecheck": "tsc --noEmit",
|
|
@@ -66,8 +79,14 @@
|
|
|
66
79
|
"magic-string": "^0.30.17"
|
|
67
80
|
},
|
|
68
81
|
"devDependencies": {
|
|
82
|
+
"@testing-library/dom": "10.4.1",
|
|
83
|
+
"@testing-library/react": "16.3.3",
|
|
69
84
|
"@types/node": "^24.0.0",
|
|
85
|
+
"@types/react": "19.3.0",
|
|
86
|
+
"@types/react-dom": "19.3.0",
|
|
70
87
|
"jsdom": "^24.0.0",
|
|
88
|
+
"react": "19.3.0",
|
|
89
|
+
"react-dom": "19.3.0",
|
|
71
90
|
"tsup": "^8.4.0",
|
|
72
91
|
"typescript": "^5.8.0",
|
|
73
92
|
"vitest": "^3.1.0",
|
|
@@ -75,7 +94,9 @@
|
|
|
75
94
|
},
|
|
76
95
|
"peerDependencies": {
|
|
77
96
|
"vite": ">=5.1.0",
|
|
78
|
-
"vue": ">=3.2.0"
|
|
97
|
+
"vue": ">=3.2.0",
|
|
98
|
+
"react": ">=18.0.0 <20",
|
|
99
|
+
"react-dom": ">=18.0.0 <20"
|
|
79
100
|
},
|
|
80
101
|
"pnpm": {
|
|
81
102
|
"onlyBuiltDependencies": [
|
|
@@ -109,6 +130,12 @@
|
|
|
109
130
|
"peerDependenciesMeta": {
|
|
110
131
|
"vue": {
|
|
111
132
|
"optional": true
|
|
133
|
+
},
|
|
134
|
+
"react": {
|
|
135
|
+
"optional": true
|
|
136
|
+
},
|
|
137
|
+
"react-dom": {
|
|
138
|
+
"optional": true
|
|
112
139
|
}
|
|
113
140
|
}
|
|
114
141
|
}
|