@fulgurjs/federation 5.7.1 → 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.
- package/CHANGELOG.md +23 -4
- package/DESIGN.md +3 -0
- package/README.en.md +350 -367
- package/README.md +293 -1179
- package/dist/cli.js +327 -29
- package/dist/index.cjs +72 -11
- package/dist/index.js +72 -11
- package/dist/runtime.js +1 -1
- package/docs/API.en.md +339 -0
- package/docs/API.md +914 -0
- package/docs/webpack-mf-/345/257/271/347/205/247/344/270/216/347/274/272/345/217/243.md +64 -37
- package/examples/README.md +3 -67
- package/examples/templates/README.md +88 -0
- package/examples/templates/react-host-vue-remote/README.md +18 -0
- package/examples/templates/react-host-vue-remote/package.json +11 -0
- package/examples/templates/react-host-vue-remote/pnpm-lock.yaml +1627 -0
- package/examples/templates/react-host-vue-remote/pnpm-workspace.yaml +10 -0
- package/examples/{bridge → templates/react-host-vue-remote}/react-host/README.md +8 -7
- package/examples/{bridge → templates/react-host-vue-remote}/react-host/package.json +1 -1
- package/examples/templates/react-host-vue-remote/react-host/src/fulgurjs/types/bridge-vue-remote.d/_paths.d.ts +4 -0
- package/examples/templates/react-host-vue-remote/react-host/src/fulgurjs/types/bridge-vue-remote.d/bridge.ts +3 -0
- package/examples/templates/react-host-vue-remote/react-host/src/fulgurjs/types/bridge-vue-remote.d.ts +9 -0
- package/examples/templates/react-host-vue-remote/scripts/dev.config.json +6 -0
- package/examples/templates/react-host-vue-remote/scripts/dev.mjs +173 -0
- package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/README.md +10 -5
- package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/package.json +1 -1
- package/examples/{react → templates/react-react}/README.md +9 -13
- package/examples/{react → templates/react-react}/host/README.md +6 -8
- package/examples/{react → templates/react-react}/host/package.json +1 -1
- package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/ClickButton.ts +3 -0
- package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/_paths.d.ts +4 -0
- package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/pages/DetailPage.ts +3 -0
- package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/pages/HomePage.ts +3 -0
- package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d/utils.ts +2 -0
- package/examples/templates/react-react/host/src/fulgurjs/types/react-remote.d.ts +26 -0
- package/examples/templates/react-react/package.json +11 -0
- package/examples/templates/react-react/pnpm-lock.yaml +1537 -0
- package/examples/templates/react-react/pnpm-workspace.yaml +10 -0
- package/examples/{react → templates/react-react}/remote/README.md +7 -6
- package/examples/{react → templates/react-react}/remote/package.json +1 -1
- package/examples/templates/react-react/scripts/dev.config.json +6 -0
- package/examples/templates/react-react/scripts/dev.mjs +173 -0
- package/examples/templates/showcase/README.md +109 -0
- package/examples/templates/showcase/package.json +13 -0
- package/examples/templates/showcase/pnpm-lock.yaml +1858 -0
- package/examples/templates/showcase/pnpm-workspace.yaml +12 -0
- package/examples/templates/showcase/react-host/fulgurjs.config.ts +21 -0
- package/examples/templates/showcase/react-host/index.html +13 -0
- package/examples/templates/showcase/react-host/package.json +26 -0
- package/examples/templates/showcase/react-host/src/GuardBanner.tsx +33 -0
- package/examples/templates/showcase/react-host/src/Layout.tsx +42 -0
- package/examples/templates/showcase/react-host/src/ObsPanel.tsx +44 -0
- package/examples/templates/showcase/react-host/src/demo-log.ts +74 -0
- package/examples/templates/showcase/react-host/src/fulgurjs/types/vue-remote.d/_paths.d.ts +4 -0
- package/examples/templates/showcase/react-host/src/fulgurjs/types/vue-remote.d/bridge.ts +3 -0
- package/examples/templates/showcase/react-host/src/fulgurjs/types/vue-remote.d.ts +7 -0
- package/examples/templates/showcase/react-host/src/main.tsx +33 -0
- package/examples/templates/showcase/react-host/src/pages/AboutPage.tsx +18 -0
- package/examples/templates/showcase/react-host/src/pages/BridgeVuePage.tsx +77 -0
- package/examples/templates/showcase/react-host/src/pages/HomePage.tsx +14 -0
- package/examples/templates/showcase/react-host/src/routing.ts +30 -0
- package/examples/templates/showcase/react-host/tsconfig.json +15 -0
- package/examples/templates/showcase/react-host/vite.config.ts +8 -0
- package/examples/templates/showcase/react-remote/fulgurjs.config.ts +18 -0
- package/examples/templates/showcase/react-remote/index.html +13 -0
- package/examples/templates/showcase/react-remote/package.json +25 -0
- package/examples/templates/showcase/react-remote/src/ChildLayout.tsx +48 -0
- package/examples/templates/showcase/react-remote/src/bridge.tsx +62 -0
- package/examples/templates/showcase/react-remote/src/child-bus.ts +32 -0
- package/examples/templates/showcase/react-remote/src/main.tsx +18 -0
- package/examples/templates/showcase/react-remote/src/pages/Locked.tsx +23 -0
- package/examples/templates/showcase/react-remote/src/pages/OrderDetail.tsx +36 -0
- package/examples/templates/showcase/react-remote/src/pages/OrderList.tsx +110 -0
- package/examples/templates/showcase/react-remote/src/pages/Settings.tsx +50 -0
- package/examples/templates/showcase/react-remote/src/settings-store.ts +11 -0
- package/examples/templates/showcase/react-remote/tsconfig.json +14 -0
- package/examples/templates/showcase/react-remote/vite.config.ts +14 -0
- package/examples/templates/showcase/scripts/dev.config.json +8 -0
- package/examples/templates/showcase/scripts/dev.mjs +173 -0
- package/examples/templates/showcase/vue-host/fulgurjs.config.ts +21 -0
- package/examples/templates/showcase/vue-host/index.html +13 -0
- package/examples/templates/showcase/vue-host/package.json +25 -0
- package/examples/templates/showcase/vue-host/src/App.vue +50 -0
- package/examples/templates/showcase/vue-host/src/GuardBanner.vue +24 -0
- package/examples/templates/showcase/vue-host/src/ObsPanel.vue +60 -0
- package/examples/templates/showcase/vue-host/src/demo-log.ts +49 -0
- package/examples/templates/showcase/vue-host/src/fulgurjs/types/react-remote.d/_paths.d.ts +4 -0
- package/examples/templates/showcase/vue-host/src/fulgurjs/types/react-remote.d/bridge.ts +3 -0
- package/examples/templates/showcase/vue-host/src/fulgurjs/types/react-remote.d.ts +7 -0
- package/examples/templates/showcase/vue-host/src/guard.ts +47 -0
- package/examples/templates/showcase/vue-host/src/main.ts +30 -0
- package/examples/templates/showcase/vue-host/src/pages/AboutPage.vue +17 -0
- package/examples/templates/showcase/vue-host/src/pages/BridgeReactPage.vue +74 -0
- package/examples/templates/showcase/vue-host/src/pages/HomePage.vue +13 -0
- package/examples/templates/showcase/vue-host/src/routing.ts +31 -0
- package/examples/templates/showcase/vue-host/tsconfig.json +14 -0
- package/examples/templates/showcase/vue-remote/fulgurjs.config.ts +17 -0
- package/examples/templates/showcase/vue-remote/index.html +13 -0
- package/examples/templates/showcase/vue-remote/package.json +23 -0
- package/examples/templates/showcase/vue-remote/src/ChildLayout.vue +54 -0
- package/examples/templates/showcase/vue-remote/src/bridge.ts +48 -0
- package/examples/templates/showcase/vue-remote/src/child-bus.ts +32 -0
- package/examples/templates/showcase/vue-remote/src/main.ts +16 -0
- package/examples/templates/showcase/vue-remote/src/pages/Locked.vue +28 -0
- package/examples/templates/showcase/vue-remote/src/pages/OrderDetail.vue +46 -0
- package/examples/templates/showcase/vue-remote/src/pages/OrderList.vue +116 -0
- package/examples/templates/showcase/vue-remote/src/pages/Settings.vue +34 -0
- package/examples/templates/showcase/vue-remote/src/settings-store.ts +13 -0
- package/examples/templates/showcase/vue-remote/tsconfig.json +14 -0
- package/examples/templates/showcase/vue-remote/vite.config.ts +14 -0
- package/examples/templates/vue-host-react-remote/README.md +18 -0
- package/examples/templates/vue-host-react-remote/package.json +11 -0
- package/examples/templates/vue-host-react-remote/pnpm-lock.yaml +1663 -0
- package/examples/templates/vue-host-react-remote/pnpm-workspace.yaml +10 -0
- package/examples/{bridge → templates/vue-host-react-remote}/react-remote/README.md +9 -4
- package/examples/{bridge → templates/vue-host-react-remote}/react-remote/package.json +1 -1
- package/examples/templates/vue-host-react-remote/scripts/dev.config.json +6 -0
- package/examples/templates/vue-host-react-remote/scripts/dev.mjs +173 -0
- package/examples/{bridge → templates/vue-host-react-remote}/vue-host/README.md +8 -7
- package/examples/{bridge → templates/vue-host-react-remote}/vue-host/package.json +1 -1
- package/examples/{bridge → templates/vue-host-react-remote}/vue-host/src/App.vue +1 -1
- package/examples/templates/vue-host-react-remote/vue-host/src/fulgurjs/types/bridge-react-remote.d/_paths.d.ts +4 -0
- package/examples/templates/vue-host-react-remote/vue-host/src/fulgurjs/types/bridge-react-remote.d/bridge.ts +3 -0
- package/examples/templates/vue-host-react-remote/vue-host/src/fulgurjs/types/bridge-react-remote.d.ts +9 -0
- package/examples/{vue → templates/vue-vue}/README.md +9 -13
- package/examples/{vue → templates/vue-vue}/host/README.md +6 -8
- package/examples/{vue → templates/vue-vue}/host/package.json +1 -1
- package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/ClickButton.ts +4 -0
- package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/_paths.d.ts +4 -0
- package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/pages/DetailPage.ts +4 -0
- package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/pages/HomePage.ts +4 -0
- package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d/utils.ts +2 -0
- package/examples/templates/vue-vue/host/src/fulgurjs/types/vue-remote.d.ts +29 -0
- package/examples/templates/vue-vue/host/vite.config.ts +8 -0
- package/examples/templates/vue-vue/package.json +11 -0
- package/examples/templates/vue-vue/pnpm-lock.yaml +1199 -0
- package/examples/templates/vue-vue/pnpm-workspace.yaml +10 -0
- package/examples/{vue → templates/vue-vue}/remote/README.md +7 -6
- package/examples/{vue → templates/vue-vue}/remote/package.json +1 -1
- package/examples/{vue → templates/vue-vue}/remote/src/App.vue +1 -1
- package/examples/templates/vue-vue/scripts/dev.config.json +6 -0
- package/examples/templates/vue-vue/scripts/dev.mjs +173 -0
- package/package.json +8 -6
- package/examples/README.en.md +0 -67
- package/examples/bridge/README.md +0 -36
- package/examples/bridge/react-host/package-lock.json +0 -2466
- package/examples/bridge/react-remote/package-lock.json +0 -2391
- package/examples/bridge/vue-host/package-lock.json +0 -1894
- package/examples/bridge/vue-remote/package-lock.json +0 -1865
- package/examples/react/host/package-lock.json +0 -2391
- package/examples/react/remote/package-lock.json +0 -2333
- package/examples/vue/host/package-lock.json +0 -1865
- package/examples/vue/remote/package-lock.json +0 -1843
- /package/examples/{bridge → templates/react-host-vue-remote}/react-host/fulgurjs.config.ts +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/react-host/index.html +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/react-host/src/env.d.ts +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/react-host/src/host-session.ts +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/react-host/src/main.tsx +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/react-host/tsconfig.json +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/react-host/vite.config.ts +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/fulgurjs.config.ts +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/index.html +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/src/App.vue +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/src/bridge.ts +0 -0
- /package/examples/{bridge/react-remote → templates/react-host-vue-remote/vue-remote}/src/env.d.ts +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/src/main.ts +0 -0
- /package/examples/{bridge/vue-host → templates/react-host-vue-remote/vue-remote}/tsconfig.json +0 -0
- /package/examples/{bridge → templates/react-host-vue-remote}/vue-remote/vite.config.ts +0 -0
- /package/examples/{react → templates/react-react}/host/fulgurjs.config.ts +0 -0
- /package/examples/{react → templates/react-react}/host/index.html +0 -0
- /package/examples/{react → templates/react-react}/host/src/App.tsx +0 -0
- /package/examples/{react → templates/react-react}/host/src/main.tsx +0 -0
- /package/examples/{react → templates/react-react}/host/src/pages/UtilsDemo.tsx +0 -0
- /package/examples/{react → templates/react-react}/host/src/remotePages.tsx +0 -0
- /package/examples/{bridge/react-remote → templates/react-react/host}/tsconfig.json +0 -0
- /package/examples/{react → templates/react-react}/host/vite.config.ts +0 -0
- /package/examples/{react → templates/react-react}/remote/fulgurjs.config.ts +0 -0
- /package/examples/{react → templates/react-react}/remote/index.html +0 -0
- /package/examples/{react → templates/react-react}/remote/src/App.tsx +0 -0
- /package/examples/{react → templates/react-react}/remote/src/exposes/ClickButton.tsx +0 -0
- /package/examples/{react → templates/react-react}/remote/src/exposes/pages/DetailPage.tsx +0 -0
- /package/examples/{react → templates/react-react}/remote/src/exposes/pages/HomePage.tsx +0 -0
- /package/examples/{react → templates/react-react}/remote/src/exposes/utils.ts +0 -0
- /package/examples/{react → templates/react-react}/remote/src/main.tsx +0 -0
- /package/examples/{react/host → templates/react-react/remote}/tsconfig.json +0 -0
- /package/examples/{react → templates/react-react}/remote/vite.config.ts +0 -0
- /package/examples/{vue/host → templates/showcase/vue-host}/vite.config.ts +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/fulgurjs.config.ts +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/index.html +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/src/bridge.tsx +0 -0
- /package/examples/{bridge/vue-host → templates/vue-host-react-remote/react-remote}/src/env.d.ts +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/src/main.tsx +0 -0
- /package/examples/{react/remote → templates/vue-host-react-remote/react-remote}/tsconfig.json +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/react-remote/vite.config.ts +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/fulgurjs.config.ts +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/index.html +0 -0
- /package/examples/{bridge/vue-remote → templates/vue-host-react-remote/vue-host}/src/env.d.ts +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/src/host-session.ts +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/src/main.ts +0 -0
- /package/examples/{bridge/vue-remote → templates/vue-host-react-remote/vue-host}/tsconfig.json +0 -0
- /package/examples/{bridge → templates/vue-host-react-remote}/vue-host/vite.config.ts +0 -0
- /package/examples/{vue → templates/vue-vue}/host/fulgurjs.config.ts +0 -0
- /package/examples/{vue → templates/vue-vue}/host/index.html +0 -0
- /package/examples/{vue → templates/vue-vue}/host/src/App.vue +0 -0
- /package/examples/{vue → templates/vue-vue}/host/src/main.ts +0 -0
- /package/examples/{vue → templates/vue-vue}/host/src/pages/HomePage.vue +0 -0
- /package/examples/{vue → templates/vue-vue}/host/src/pages/UtilsDemo.vue +0 -0
- /package/examples/{vue → templates/vue-vue}/host/tsconfig.json +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/fulgurjs.config.ts +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/index.html +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/src/exposes/ClickButton.vue +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/src/exposes/pages/DetailPage.vue +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/src/exposes/pages/HomePage.vue +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/src/exposes/utils.ts +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/src/main.ts +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/tsconfig.json +0 -0
- /package/examples/{vue → templates/vue-vue}/remote/vite.config.ts +0 -0
package/README.en.md
CHANGED
|
@@ -1,476 +1,459 @@
|
|
|
1
1
|
# @fulgurjs/federation
|
|
2
2
|
|
|
3
|
-
[
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
3
|
+
**[All templates and demos](examples/README.en.md)**: Example catalog and run guide.
|
|
4
|
+
|
|
5
|
+
[简体中文](README.md) | [English](README.en.md)
|
|
6
|
+
|
|
7
|
+
**Use components, pages and functions from another Vite application.**
|
|
8
|
+
|
|
9
|
+
For example, a main application can load a separately deployed approval page, a Vue host can embed a React sub-app, or several applications can use the same utility module. Each application can live in its own repository and build and deploy separately.
|
|
10
|
+
|
|
11
|
+
This is the usage guide. Examples and templates are written against **5.8.0** (the exact version in each project's `package.json` is what gets installed). Signatures, defaults and execution rules are in the [API reference](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md).
|
|
12
|
+
|
|
13
|
+
## Choose what you need
|
|
14
|
+
|
|
15
|
+
| Goal | Use | Example |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Load a Vue component in Vue | `remoteComponent` | [Vue examples](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates/vue-vue) |
|
|
18
|
+
| Load a React component in React | `remoteComponent` from `/react` | [React examples](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates/react-react) |
|
|
19
|
+
| Call a remote JS/TS function | `loadRemote`; React also has `useLoadRemote` | Quick start below |
|
|
20
|
+
| Map several host routes to remote pages | `createHostPages` (Vue) / `createReactHostPages` (React) | [Page demo](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/demos/pages-cli) |
|
|
21
|
+
| Embed Vue in React, or React in Vue | `defineBridgeApp` + a host bridge component | [Bridge examples](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates) |
|
|
22
|
+
| Restore a sub-app detail route after refresh | Enable bridge URL sync | [Router demo](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates/showcase) |
|
|
23
|
+
| Provide user data or run remote initialization | `AppContext`, optional `setup`/`onSession` | Initialization below |
|
|
24
|
+
| Run React 18 and 19 on the same page | Separate dependency groups and consumers using `shareScope` | [Version isolation demo](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/demos/react-versions) |
|
|
25
|
+
|
|
26
|
+
Combine these features as needed. **A simple remote component does not require a bridge, page table or login lifecycle.**
|
|
27
|
+
|
|
28
|
+
## Terms in plain language
|
|
29
|
+
|
|
30
|
+
| Term | Meaning |
|
|
31
|
+
|---|---|
|
|
32
|
+
| Host | The application displaying remote content |
|
|
33
|
+
| Remote | The application providing a module |
|
|
34
|
+
| `exposes` | Files the remote allows other applications to load |
|
|
35
|
+
| `remotes` | The remote names and addresses the host uses |
|
|
36
|
+
| `shared` | Dependencies that participate in sharing, such as Vue or React |
|
|
37
|
+
| `singleton` | Adopt one dependency instance within a share scope; this does not make incompatible major versions compatible |
|
|
38
|
+
| `shareScope` | A group of shared dependencies; separate groups can use separate versions |
|
|
39
|
+
| Bridge | A DOM container in which a sub-app manages its own rendering and cleanup |
|
|
40
|
+
| URL sync | Record the sub-app route in the host URL so refresh, sharing and history navigation can restore it |
|
|
41
|
+
|
|
42
|
+
An application can both expose and consume modules.
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
Install in every participating Vite project:
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
49
|
pnpm add -D @fulgurjs/federation
|
|
50
|
+
# npm projects: npm install -D @fulgurjs/federation
|
|
49
51
|
```
|
|
50
52
|
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
- Chrome 108+
|
|
53
|
+
- Supports browser applications using Vue 3, React 18/19, and plain JS/TS modules.
|
|
54
|
+
- Supports Vite 5.1+ within the Vite 5/6/7/8 series. Your framework plugins must also support your chosen Vite version.
|
|
55
|
+
- The plugin requires Node.js ≥18, but **Vite 7/8 require Node.js 20.19+ or 22.12+**. Meet both requirements.
|
|
56
|
+
- Set the build target to `es2022` or newer. Chrome 108+ is the browser baseline; other browsers need corresponding ESM, dynamic import and top-level await support.
|
|
57
|
+
- A pure Vue application needs Vue; a pure React application needs React and react-dom. A cross-framework bridge host installs both frameworks as explained below.
|
|
58
|
+
|
|
59
|
+
## Starting fresh: create a complete project
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
Without an existing project, scaffold from a complete template with the CLI (Node ≥ 20 and pnpm ≥ 9 required):
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
```bash
|
|
64
|
+
npx @fulgurjs/federation create # interactive; or explicit:
|
|
65
|
+
npx @fulgurjs/federation create vue-vue --dir my-federation
|
|
66
|
+
```
|
|
59
67
|
|
|
60
|
-
|
|
68
|
+
Five templates cover Vue×Vue, React×React, a Vue host embedding a React child app, a React host embedding a Vue child app, and the bidirectional bridge + URL sync showcase. `create` copies a runnable workspace (lockfile and startup script included) and runs a frozen install by default, then prints the commands to enter, start and build. For an **existing** project skip this and use the quick start below plus `fulgurjs init`.
|
|
61
69
|
|
|
62
|
-
|
|
70
|
+
Template sources live in [examples/templates/](examples/templates/README.md); no manual wiring is needed unless you change names/ports (fixed checklist in the template guide).
|
|
63
71
|
|
|
64
|
-
|
|
65
|
-
// vite.config.ts
|
|
66
|
-
import { defineConfig } from 'vite'
|
|
67
|
-
import react from '@vitejs/plugin-react' // or @vitejs/plugin-vue
|
|
68
|
-
import federation from '@fulgurjs/federation'
|
|
69
|
-
import fulgurjsConfig from './fulgurjs.config.ts'
|
|
72
|
+
## Quick start: two Vue applications
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
```
|
|
74
|
+
These steps add federation to **existing Vite + Vue projects**, which retain their own HTML and application entry files.
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
```text
|
|
77
|
+
remote-vue/ Provides a button and add() function; dev port 5174
|
|
78
|
+
host-vue/ Loads them; dev port 5173
|
|
79
|
+
```
|
|
75
80
|
|
|
76
|
-
|
|
81
|
+
### 1. Declare remote files
|
|
77
82
|
|
|
78
|
-
|
|
83
|
+
`remote-vue/fulgurjs.config.ts`:
|
|
79
84
|
|
|
80
85
|
```ts
|
|
81
|
-
// remote: fulgurjs.config.ts
|
|
82
86
|
import type { FederationOptions } from '@fulgurjs/federation'
|
|
83
87
|
|
|
84
88
|
export default {
|
|
85
|
-
name: 'remote-
|
|
89
|
+
name: 'remote-vue',
|
|
86
90
|
exposes: {
|
|
87
|
-
'./Button': './src/Button.
|
|
88
|
-
'./
|
|
89
|
-
'./pages/home': './src/pages/Home.tsx',
|
|
90
|
-
},
|
|
91
|
-
shared: {
|
|
92
|
-
react: { singleton: true },
|
|
93
|
-
'react-dom': { singleton: true },
|
|
91
|
+
'./Button': './src/Button.vue',
|
|
92
|
+
'./math': './src/math.ts',
|
|
94
93
|
},
|
|
94
|
+
shared: { vue: { singleton: true, strictVersion: true } },
|
|
95
95
|
} satisfies FederationOptions
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
`remote-vue/src/Button.vue`:
|
|
99
99
|
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
import {
|
|
100
|
+
```vue
|
|
101
|
+
<script setup lang="ts">
|
|
102
|
+
import { ref } from 'vue'
|
|
103
|
+
defineProps<{ label: string }>()
|
|
104
|
+
const count = ref(0)
|
|
105
|
+
</script>
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
})
|
|
107
|
+
<template>
|
|
108
|
+
<button @click="count++">{{ label }}: {{ count }}</button>
|
|
109
|
+
</template>
|
|
110
|
+
```
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
type Utils = { formatMoney(v: number, currency?: string): string }
|
|
112
|
+
`remote-vue/src/math.ts`:
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
```ts
|
|
115
|
+
export function add(a: number, b: number): number {
|
|
116
|
+
return a + b
|
|
117
|
+
}
|
|
116
118
|
```
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
### 2. Declare the address in the host
|
|
121
|
+
|
|
122
|
+
`host-vue/fulgurjs.config.ts`:
|
|
119
123
|
|
|
120
|
-
|
|
124
|
+
```ts
|
|
125
|
+
import type { FederationOptions } from '@fulgurjs/federation'
|
|
121
126
|
|
|
122
|
-
|
|
127
|
+
export default {
|
|
128
|
+
name: 'host-vue',
|
|
129
|
+
remotes: {
|
|
130
|
+
'remote-vue': {
|
|
131
|
+
dev: 'http://localhost:5174',
|
|
132
|
+
prod: '/remote-vue',
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
shared: { vue: { singleton: true, strictVersion: true } },
|
|
136
|
+
} satisfies FederationOptions
|
|
137
|
+
```
|
|
123
138
|
|
|
124
|
-
|
|
139
|
+
`dev` is the development URL. `prod` is the deployed URL; `/remote-vue` refers to a path on the host origin, not a local filesystem folder.
|
|
125
140
|
|
|
126
|
-
|
|
141
|
+
### 3. Register the plugin in both applications
|
|
127
142
|
|
|
128
|
-
|
|
143
|
+
Each project's `vite.config.ts` imports its own federation config:
|
|
129
144
|
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
--require-verified # page-table ↔ remote manifest contract check (CI gate)
|
|
136
|
-
npx fulgurjs doctor --site https://example.com # deployment health check
|
|
137
|
-
```
|
|
145
|
+
```ts
|
|
146
|
+
import { defineConfig } from 'vite'
|
|
147
|
+
import vue from '@vitejs/plugin-vue'
|
|
148
|
+
import federation from '@fulgurjs/federation'
|
|
149
|
+
import fulgurjsConfig from './fulgurjs.config'
|
|
138
150
|
|
|
139
|
-
|
|
151
|
+
export default defineConfig({
|
|
152
|
+
plugins: [vue(), federation(fulgurjsConfig)],
|
|
153
|
+
build: { target: 'es2022' },
|
|
154
|
+
})
|
|
155
|
+
```
|
|
140
156
|
|
|
141
|
-
|
|
157
|
+
Keep existing aliases, proxies and other settings. Install compatible Vue versions in both applications; `strictVersion` rejects incompatible shared versions.
|
|
142
158
|
|
|
143
|
-
###
|
|
159
|
+
### 4. Display and call the remote modules
|
|
144
160
|
|
|
145
|
-
|
|
161
|
+
`host-vue/src/App.vue`:
|
|
146
162
|
|
|
147
|
-
|
|
163
|
+
```vue
|
|
164
|
+
<script setup lang="ts">
|
|
165
|
+
import { ref } from 'vue'
|
|
166
|
+
import { loadRemote, remoteComponent } from '@fulgurjs/federation/runtime'
|
|
148
167
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
| `fallback` | `ReactNode`, default `null` | placeholder while this load is pending (distinct from the failure placeholder) |
|
|
152
|
-
| `error` | `ReactNode` or `(error, retry) => ReactNode`, default built-in Chinese placeholder | shown on load failure **or** subtree render error; the function receives the real error and a working retry |
|
|
153
|
-
| `retries` | `number` (integer 0–10), default follows `loadRemote` (2) | passthrough; invalid values throw at factory call |
|
|
154
|
-
| `timeout` | `number` (ms), default none | adapter-level wait cap for this component load; does **not** cancel the issued shared request; late results never overwrite the settled state and produce no unhandled rejections |
|
|
168
|
+
const RemoteButton = remoteComponent('remote-vue/Button')
|
|
169
|
+
const result = ref('Not calculated yet')
|
|
155
170
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
171
|
+
async function calculate() {
|
|
172
|
+
try {
|
|
173
|
+
const math = await loadRemote<{ add(a: number, b: number): number }>('remote-vue/math')
|
|
174
|
+
result.value = String(math.add(1, 2))
|
|
175
|
+
} catch (error) {
|
|
176
|
+
result.value = error instanceof Error ? error.message : String(error)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
</script>
|
|
163
180
|
|
|
164
|
-
|
|
181
|
+
<template>
|
|
182
|
+
<RemoteButton label="Remote button" />
|
|
183
|
+
<button @click="calculate">Call remote add()</button>
|
|
184
|
+
<p>{{ result }}</p>
|
|
185
|
+
</template>
|
|
186
|
+
```
|
|
165
187
|
|
|
166
|
-
- `
|
|
167
|
-
- Options: `shareScope`, `retries`, `fallbackModule` (explicit degradation — failures return the fallback value instead of writing `error`)
|
|
168
|
-
- Uniform state contract: first load, spec/option/session change and explicit `reload` all enter `data=undefined, error=undefined, loading=true`; the current attempt writes `data` on success or `error` on failure and clears `loading`; stale attempts never write
|
|
169
|
-
- Generation guards: fast A→B switching, late slow responses, consecutive reloads, unmount-during-flight and StrictMode double effects can only write from the latest valid request
|
|
170
|
-
- `reload` clears old data and re-runs the lifecycle (onSession dedup by generation) but never re-downloads cached successful modules; resolves normally (failures surface in `error`, never an unhandled rejection). Unmount invalidates pending effects and reloads; calling a saved reload after unmount starts no request
|
|
171
|
-
- Session-aware: re-runs when `sessionKey` changes; same-session re-renders don't
|
|
188
|
+
In `remote-vue/Button`, `remote-vue` matches the host's `remotes` key and `Button` matches the remote's `./Button` expose key. The `./` can be omitted when loading it.
|
|
172
189
|
|
|
173
|
-
|
|
190
|
+
`loadRemote` returns module exports. You still need to call `math.add()` to perform the calculation.
|
|
174
191
|
|
|
175
|
-
|
|
192
|
+
### 5. Run both applications
|
|
176
193
|
|
|
177
|
-
|
|
194
|
+
```bash
|
|
195
|
+
# Terminal one, inside remote-vue
|
|
196
|
+
npm run dev -- --port 5174 --strictPort
|
|
178
197
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
- No `keepAliveNames` / no keep-alive promise (Vue-specific); routing is not a runtime dependency — render `component(spec)` output from your router (React Router examples in `examples/react/host`; route params reach remote pages as props)
|
|
183
|
-
- Cross-framework Context: host and remote get the **same Context object** through the same expose instance; the plugin does not auto-bridge arbitrary React Contexts
|
|
198
|
+
# Terminal two, inside host-vue
|
|
199
|
+
npm run dev -- --port 5173 --strictPort
|
|
200
|
+
```
|
|
184
201
|
|
|
185
|
-
|
|
202
|
+
Open `http://localhost:5173`. The remote button should count clicks, and the calculation should display `3`. pnpm projects can use `pnpm dev` instead.
|
|
186
203
|
|
|
187
|
-
|
|
204
|
+
Complete projects and deployment configuration: [Vue examples](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates/vue-vue).
|
|
188
205
|
|
|
189
|
-
|
|
206
|
+
## React setup
|
|
190
207
|
|
|
191
|
-
|
|
208
|
+
Use the same configuration structure with these changes:
|
|
192
209
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
| `loadShare` | `(name: string, opts?: LoadShareOptions) => Promise<any>` | shared-deps negotiation: `requiredVersion` (semver or `false`), `singleton`, `strictVersion`, `shareKey`, `shareScope`, `fallback: () => Promise<any>`. Highest satisfying version wins; loaded versions never replaced; singleton keeps one instance (warns MFU-010 when the reused version doesn't satisfy `requiredVersion`; throws MFU-003 with `strictVersion`) |
|
|
197
|
-
| `initSharing` | `(scopeName?: string) => ShareScopeMap` (default `'default'`) | creates/returns the share scope map (usually called for you by the injected init) |
|
|
198
|
-
| `registerShare` | `(scopeName, name, version, get: () => Promise<any>, opts?: { from?, eager?, loaded? }) => void` | register a provided shared module at runtime; first registration of a version wins |
|
|
199
|
-
| `registerRemote` / `registerRemotes` | `(config: RemoteConfig) => void` / `((list: RemoteConfig[]) => void)` | runtime registration: `{ name, entry, shareScope?, timeout?, retries?, fallback?, breaker?, promise? }`. Promise-based remotes pass `promise: () => Promise<container>` |
|
|
200
|
-
| `registerPlugins` | `(plugins: RuntimePlugin[]) => void` | register runtime plugins; each `init(hooks)` may set `resolveShare`, `beforeLoadRemote({ remote, module })`, `afterLoadRemote({ remote, module, module_ns })`, `onRemoteError({ remote, error })`. Observer-hook failures warn but never break loading |
|
|
201
|
-
| `preloadRemote` | `(spec: string, opts?: { mode?: 'preload' \| 'prefetch' }) => Promise<void>` | manifest-driven preload of entry + expose chunks + CSS; `'prefetch'` = low priority. No lifecycle side effects (setup/onSession are NOT run) |
|
|
202
|
-
| `getContainer` | `(name: string) => Promise<any>` | acquire the initialized container |
|
|
203
|
-
| `getRuntime` | `() => FgRuntime` | the page-level runtime singleton (`globalThis.__FULGURJS_RUNTIME__`) |
|
|
204
|
-
| `parseSpec` | `(spec: string) => { remote, module }` | synchronous spec parsing |
|
|
205
|
-
| `shareScopeMap` | `ShareScopeMap` | live registry (debug surface: `window.__FULGURJS_SCOPE__`) |
|
|
206
|
-
| `unwrapDefault` | `(ns: any) => any` | ESM/CJS default-interop helper |
|
|
207
|
-
| `version` | `string` | plugin/runtime version |
|
|
208
|
-
| `clearSessionState` | `() => void` | invalidate all remotes' session signals and onSession dedup state (called by `clearAppContext`) |
|
|
209
|
-
|
|
210
|
-
Remote-registration config fields: `timeout` (ms, default 15000 — ends the caller's wait, never cancels the issued import), `retries` (0–10, default 2), `fallback: string[]` (spare entry URLs), `breaker: { threshold, resetMs }` (default 5 / 30s).
|
|
211
|
-
|
|
212
|
-
### 8.3 Plugin options — `federation(options)`
|
|
213
|
-
|
|
214
|
-
| Option | Type / default | Notes |
|
|
215
|
-
|---|---|---|
|
|
216
|
-
| `name` | `string`, **required** | container name; unique per page; `/^[a-zA-Z][\w.-]*$/` |
|
|
217
|
-
| `exposes` | `Record<string, string \| { import, name? }>` | key normalized to `./Key`; stable chunk name optional |
|
|
218
|
-
| `remotes` | `Record<string, string \| RemoteEntryConfig \| (() => Promise<any>)>` | string = url or `name@url`; object = `{ external?, dev?, prod?, timeout?, retries?, fallback?, breaker?, shareScope? }`; function = promise-based remote (runtime-register instead) |
|
|
219
|
-
| `shared` | `string[]` or `Record<string, string \| SharedHint>` | see below |
|
|
220
|
-
| `setup` | `string` | module path; must default-export `setup(context)`, optional named `onSession(context)` |
|
|
221
|
-
| `shareScope` | `string`, default `'default'` | default scope for provides |
|
|
222
|
-
| `filename` | `string`, default `'fulgurjs-remoteEntry.js'` | fixed remoteEntry filename |
|
|
223
|
-
| `manifest` | `boolean`, default `true` | emit `fulgurjs-manifest.json` |
|
|
224
|
-
| `dts` | `boolean \| { dir?, mode?: 'source' \| 'shim' }`, default `true` | dev type generation (see §8.6) |
|
|
225
|
-
| `devSharedSelf` | `boolean`, default inferred | pure remotes & dual-role apps: `true` (dev shared rewriting); pure hosts: `false` |
|
|
226
|
-
| `devCorsOrigins` | `'*'` or `string[]` | dev endpoints + server.cors share the policy; explicit user `server.cors` wins |
|
|
227
|
-
| `devFsRoot` | `boolean`, default `true` | dev manifest carries local fsRoot for type direct-connect; `false` → host falls back to `any` stubs |
|
|
228
|
-
| `runtimePlugins` | `string[]` | modules default-exporting a `RuntimePlugin` |
|
|
229
|
-
|
|
230
|
-
`SharedHint` fields: `import` (local specifier or `false` = pure consumer), `packageName` (infer `requiredVersion` from a different package name), `requiredVersion` (semver or `false`), `singleton`, `strictVersion` (default: `true` when a local fallback exists and not singleton, webpack-aligned), `shareKey`, `shareScope`, `eager`, `version`.
|
|
231
|
-
|
|
232
|
-
### 8.4 Lifecycle — `setup` / `onSession`
|
|
210
|
+
1. Use `@vitejs/plugin-react` in `vite.config.ts`, followed by `federation(fulgurjsConfig)`.
|
|
211
|
+
2. Expose `./Button` from `./src/Button.tsx`; configure the remote's address in the host.
|
|
212
|
+
3. Both applications use compatible React/renderer versions and share:
|
|
233
213
|
|
|
234
214
|
```ts
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
export async function onSession(ctx: { appContext: any; sessionKey: string; signal: AbortSignal }) {
|
|
240
|
-
// session-level: once per host sessionKey (login generation); re-login re-runs, logout invalidates
|
|
215
|
+
shared: {
|
|
216
|
+
react: { singleton: true, strictVersion: true },
|
|
217
|
+
'react-dom': { singleton: true, strictVersion: true },
|
|
241
218
|
}
|
|
242
219
|
```
|
|
243
220
|
|
|
244
|
-
|
|
245
|
-
- `signal` aborts on logout/session change — check `signal.aborted` before writing async results
|
|
246
|
-
- `preloadRemote` / `getContainer` never trigger the lifecycle
|
|
247
|
-
- Remote declares `onSession` → the host **must** provide a non-empty `sessionKey` (MFU-013); never use a token as sessionKey
|
|
248
|
-
- No-setup remotes (plain public components) load normally without any context
|
|
249
|
-
|
|
250
|
-
### 8.5 AppContext — cross-app values
|
|
251
|
-
|
|
252
|
-
- `provideAppContext(partial)` — merge-write the page-level singleton (idempotent; later writes win). Host bridge calls it after login and re-calls on account change; then triggers its own re-render
|
|
253
|
-
- `getAppContext()` — read the snapshot (`CC-002` if loaded outside the host federation)
|
|
254
|
-
- `requireAppContext(...keys)` — validated read; missing keys → `CC-001` with got/expected/example
|
|
255
|
-
- `clearAppContext()` — delete context + invalidate session signals/dedup (module and share caches, and completed app-level setup, are preserved). Logout must call it before unmounting authed UI
|
|
256
|
-
- Standard fields: `user`, `getToken()`, `store` (host pinia), `hostApp` (host Vue app), `locale`, `events`, `sessionKey` — plus arbitrary extension keys. Transport snapshot + function references; not reactive
|
|
221
|
+
Remote `src/Button.tsx`:
|
|
257
222
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
- Zero config: ambient declarations per expose — imports resolve, exports typed `any`; setup entry never generates declarations
|
|
261
|
-
- Precise track: add `"paths": { "<remote>/*": ["<typesDir>/<remote>.d/*"] }` to the app's **effective TS context** — `tsconfig.json` itself, its `extends` chain, or a referenced sub-project whose `include` covers the app source / types output dir. Standalone `tsconfig.test.json`, `tsconfig.node.json` (vite.config only) and other unrelated configs do not affect the decision; imports then resolve through forwarder modules to **source-level types** (wrong props/arguments fail compilation). Remotes covered by paths automatically skip their loose declaration to avoid shadowing
|
|
223
|
+
```tsx
|
|
224
|
+
import { useState } from 'react'
|
|
262
225
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
226
|
+
export default function Button({ label }: { label: string }) {
|
|
227
|
+
const [count, setCount] = useState(0)
|
|
228
|
+
return <button onClick={() => setCount(count + 1)}>{label}: {count}</button>
|
|
229
|
+
}
|
|
230
|
+
```
|
|
267
231
|
|
|
268
|
-
|
|
232
|
+
Host `src/App.tsx`, with a remote configured as `remote-react`:
|
|
269
233
|
|
|
270
|
-
|
|
234
|
+
```tsx
|
|
235
|
+
import { remoteComponent } from '@fulgurjs/federation/react'
|
|
271
236
|
|
|
272
|
-
|
|
237
|
+
// Create once at module scope, not on every render.
|
|
238
|
+
const RemoteButton = remoteComponent<{ label: string }>('remote-react/Button', {
|
|
239
|
+
fallback: <p>Loading…</p>,
|
|
240
|
+
})
|
|
273
241
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
React sub-app @fulgurjs/federation/react -> defineBridgeApp (zero Vue; react-dom/client loads at mount time)
|
|
278
|
-
bridge host @fulgurjs/federation/bridge/vue -> createVueBridgeApp (recommended for Vue hosts; zero React)
|
|
279
|
-
@fulgurjs/federation/bridge/react -> createReactBridgeApp (recommended for React hosts; zero Vue)
|
|
280
|
-
@fulgurjs/federation/bridge -> aggregate (kept for compatibility; dev native ESM executes both host adapters)
|
|
242
|
+
export default function App() {
|
|
243
|
+
return <RemoteButton label="Remote React button" />
|
|
244
|
+
}
|
|
281
245
|
```
|
|
282
246
|
|
|
283
|
-
|
|
247
|
+
React also imports `loadRemote` and `useLoadRemote` from `/react` for ordinary modules. Complete projects: [React examples](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates/react-react).
|
|
284
248
|
|
|
285
|
-
|
|
249
|
+
## Embed Vue and React in each other
|
|
286
250
|
|
|
287
|
-
|
|
251
|
+
**A bridge embeds a sub-app with its own component tree. It does not convert a React component into a Vue component.**
|
|
288
252
|
|
|
289
|
-
|
|
253
|
+
For a Vue host embedding React:
|
|
290
254
|
|
|
291
|
-
|
|
292
|
-
// Vue sub-app src/bridge.ts
|
|
293
|
-
import { createApp } from 'vue'
|
|
294
|
-
import { createMemoryHistory, createRouter } from 'vue-router'
|
|
295
|
-
import { defineBridgeApp } from '@fulgurjs/federation/runtime'
|
|
296
|
-
export default defineBridgeApp((props) => {
|
|
297
|
-
const app = createApp(App, props)
|
|
298
|
-
app.use(createRouter({ history: createMemoryHistory(), routes }))
|
|
299
|
-
return app
|
|
300
|
-
})
|
|
301
|
-
```
|
|
255
|
+
1. React remote `src/bridge.tsx`:
|
|
302
256
|
|
|
303
257
|
```tsx
|
|
304
|
-
// React sub-app src/bridge.tsx
|
|
305
|
-
import { MemoryRouter } from 'react-router-dom'
|
|
306
258
|
import { defineBridgeApp } from '@fulgurjs/federation/react'
|
|
307
|
-
export default defineBridgeApp((props) => <MemoryRouter><App {...props} /></MemoryRouter>)
|
|
308
|
-
```
|
|
309
259
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
- Errors inside the sub-app after the first commit belong to **the sub-app's own error boundary** — host boundaries cannot catch cross-root render errors.
|
|
260
|
+
export default defineBridgeApp((props) => (
|
|
261
|
+
<section>React sub-app: {String(props.message ?? '')}</section>
|
|
262
|
+
))
|
|
263
|
+
```
|
|
315
264
|
|
|
316
|
-
|
|
265
|
+
2. Add `exposes: { './bridge': './src/bridge.tsx' }` to the remote config.
|
|
266
|
+
3. Configure the remote address in the Vue host, then use:
|
|
317
267
|
|
|
318
|
-
```
|
|
319
|
-
|
|
268
|
+
```vue
|
|
269
|
+
<script setup lang="ts">
|
|
320
270
|
import { createVueBridgeApp } from '@fulgurjs/federation/bridge/vue'
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
getContext: () => getLatestHostContext(), // your own synchronous pure getter
|
|
324
|
-
})
|
|
325
|
-
// <RemoteReactApp :session-key="loginKey" :app-props="{ userId, onReady }" />
|
|
326
|
-
```
|
|
271
|
+
const RemoteApp = createVueBridgeApp<{ message: string }>('remote-react/bridge')
|
|
272
|
+
</script>
|
|
327
273
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const RemoteVueApp = createReactBridgeApp('bridge-vue-remote/bridge', { getContext: () => getLatestHostContext() })
|
|
332
|
-
// <RemoteVueApp sessionKey={loginKey} appProps={{ userId, onReady }} />
|
|
274
|
+
<template>
|
|
275
|
+
<RemoteApp :app-props="{ message: 'From Vue host' }" />
|
|
276
|
+
</template>
|
|
333
277
|
```
|
|
334
278
|
|
|
335
|
-
|
|
279
|
+
A cross-framework host installs and shares `vue`, `react` and `react-dom`. The child installs and shares its own framework. React and react-dom must be compatible; multiple React majors need separate dependency groups and consumers, as shown in the isolation demo.
|
|
280
|
+
|
|
281
|
+
In the other direction, use `createReactBridgeApp` in the React host. The Vue child uses `defineBridgeApp` from `/runtime` and returns a `createApp(...)` application.
|
|
282
|
+
|
|
283
|
+
### The shortest bridge mental model
|
|
284
|
+
|
|
285
|
+
| Question | Answer |
|
|
286
|
+
|---|---|
|
|
287
|
+
| Which frameworks does each side install? | The bridge host installs and shares `vue` + `react` + `react-dom` (all three `singleton: true`); the child installs and shares only its own framework. This contract is mandatory — a missing key produces double instances (Invalid hook call / broken state) |
|
|
288
|
+
| What do `shared` / `singleton` do here? | They make host and child use the **same** framework instance; `singleton` converges instances but does not make incompatible majors compatible |
|
|
289
|
+
| How does the child export its entry? | The `./bridge` expose file **default-exports** the value returned by `defineBridgeApp(...)`; missing `mount`/`unmount` fails with MFU-015 |
|
|
290
|
+
| How does the host mount it? | `createVueBridgeApp('remote/bridge')` / `createReactBridgeApp(...)` return a component: render to mount, remove to unmount; pass `appProps` and optional `sessionKey` |
|
|
291
|
+
| When is URL sync needed? | Only when refresh/share/back-forward must restore the child's internal page (`routing` + `basePath`, configured on both ends). Without it, child navigation not touching the host URL is normal behavior |
|
|
292
|
+
| How do sessions and unmount work? | Login generations use `sessionKey` (new generation re-runs `onSession`; logout → `null` unmounts and empties). Unmount is driven by the host component lifecycle; a child cleanup throw blocks that container until a full page reload |
|
|
293
|
+
|
|
294
|
+
### `appProps` is a mount-time snapshot, not reactive props
|
|
295
|
+
|
|
296
|
+
Top-level fields are shallow-copied at mount; later host-side replacements do **not** update the child. Three channels for live data:
|
|
297
|
+
|
|
298
|
+
| Situation | Use | Cost |
|
|
336
299
|
|---|---|---|
|
|
337
|
-
|
|
|
338
|
-
|
|
|
339
|
-
|
|
|
300
|
+
| Child needs current host values (token, user name…) | Pass a **stable callback** (`getToken: () => store.token`) — calls read the latest value | No remount; good for "reads" |
|
|
301
|
+
| Both sides share one state | Pass the host store instance via `appProps` or AppContext; both subscribe to the same instance | Reactivity does not cross roots; the child subscribes explicitly |
|
|
302
|
+
| Must re-initialize with new props | Change the bridge component's `key` to remount explicitly (full unload → reload chain) | All state resets; do not trigger frequently |
|
|
303
|
+
|
|
304
|
+
This differs from ordinary component props on purpose — it is a structural property of cross-root mounting, not a bug. Separate component trees do not inherit Context, provide/inject or routers. Pass or install what is needed explicitly. Use `remoteComponent` for a same-framework component; use a bridge for a sub-app.
|
|
305
|
+
|
|
306
|
+
Complete bidirectional setup and login/cleanup flows: [bridge examples](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates).
|
|
340
307
|
|
|
341
|
-
|
|
342
|
-
- **`getContext`**: a synchronous, side-effect-free getter called before each actual load (first load, retry, session switch). Non-object/thenable returns → `MFU-016` (`phase: 'getContext'`). The bridge validates the snapshot's `sessionKey` against the controlled value (`MFU-017` on mismatch, without writing global state), then writes `provideAppContext` itself. On generation change the bridge clears the previous account context first (zero residue).
|
|
343
|
-
- **Controlled `sessionKey`**: accepts `undefined` (no controlled validation) / `null` (logged out: unmount immediately, keep the container empty, stop loading) / non-empty string (login generation). Illegal values → `MFU-017`.
|
|
344
|
-
- **Multi-instance**: several same-spec instances coexist (per-el keying); `AppContext` is a page-level singleton — all controlled instances on a page must share the same session (`MFU-017` otherwise). React StrictMode double-effect is safe. Vue `<KeepAlive>` deactivation is **not** an unmount. Late results from invalidated generations are dropped by generation guards; a remote `onSession` must honor the existing `signal.aborted` contract.
|
|
308
|
+
## Keep child routes in the browser URL
|
|
345
309
|
|
|
346
|
-
|
|
310
|
+
Bridging does not change the host URL by default. Enable URL sync to map:
|
|
347
311
|
|
|
348
|
-
|
|
312
|
+
```text
|
|
313
|
+
Host /approval/list → Child /list
|
|
314
|
+
Host /approval/detail/42 → Child /detail/42
|
|
315
|
+
```
|
|
349
316
|
|
|
350
|
-
|
|
317
|
+
Configure both sides:
|
|
351
318
|
|
|
352
|
-
|
|
319
|
+
1. The host router must handle all child paths under `/approval` without unmounting the child on each detail navigation.
|
|
320
|
+
2. Pass `routing` to the host bridge component, including `basePath: '/approval'` and the host navigation adapter.
|
|
321
|
+
3. The child declares `defineBridgeApp(..., { routing: true })` and connects a controlled memory router.
|
|
353
322
|
|
|
354
|
-
|
|
355
|
-
Vue: `defineBridgeApp(async (props, ctx) => { const router = createRouter({ history: createMemoryHistory(), routes }); await connectVueBridgeRouter(ctx.routing!, router).ready; ... app.use(router); return app }, { routing: true })` (await ready BEFORE `app.use(router)` — the install-time initial navigation would otherwise override the deep-link location).
|
|
356
|
-
React: `createReactBridgeRouter(ctx.routing!, routes).element` — `createMemoryRouter`-based; `Link`/`useNavigate` work unmodified.
|
|
323
|
+
Vue uses `createVueBridgeNavigation` / `connectVueBridgeRouter`; React uses `createReactBridgeNavigation` / `createReactBridgeRouter`. React hosts need a data router (`createBrowserRouter` or `createHashRouter`), not `BrowserRouter`. Built-in adapters support Vue Router 4 and React Router ≥6.11.
|
|
357
324
|
|
|
358
|
-
|
|
325
|
+
Refresh, shared links and browser history restore the route, **not form contents or business data**. See [routing API](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#url-sync) and the runnable [router demo](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates/showcase).
|
|
359
326
|
|
|
360
|
-
|
|
327
|
+
## User data and remote initialization
|
|
361
328
|
|
|
362
|
-
|
|
329
|
+
These features are optional. A plain button or utility module does not need them.
|
|
363
330
|
|
|
364
|
-
|
|
331
|
+
| Need | API | When |
|
|
332
|
+
|---|---|---|
|
|
333
|
+
| Provide user, token getter, store, etc. | `provideAppContext` | Host supplies them before loading business modules |
|
|
334
|
+
| Read host values | `getAppContext` / `requireAppContext` | Called by remote business code |
|
|
335
|
+
| Initialize a remote once | Default export in configured `setup` file | Before the first business `loadRemote('remote/module')` returns |
|
|
336
|
+
| Synchronize permissions after login/account changes | Named `onSession` export in the same file | Deduplicated by `sessionKey` |
|
|
337
|
+
| Clear account context on logout | `clearAppContext` | Host logout flow; host also removes private pages/caches |
|
|
365
338
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
339
|
+
`sessionKey` identifies a login attempt; it is **not a token or authorization credential**. Generate a new value on login/account change; token refresh alone retains it.
|
|
340
|
+
|
|
341
|
+
A bridge can read current data using `getContext`. Controlled `sessionKey: null` means logged out: unmount and stop loading. Omitting the key disables controlled session switching.
|
|
342
|
+
|
|
343
|
+
Only a configured `setup` file participates in initialization. `preloadRemote` fetches resources without running setup/onSession. Async initialization must check `context.signal.aborted` before writing state, so late responses do not restore old-account data.
|
|
344
|
+
|
|
345
|
+
See the [API reference](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#context).
|
|
346
|
+
|
|
347
|
+
## Several remote pages
|
|
348
|
+
|
|
349
|
+
Maintain a page table and pass it to `createHostPages` (Vue) or `createReactHostPages` (React). These helpers resolve modules, cache loading components and provide loading/error states. **They do not create your host Router.**
|
|
350
|
+
|
|
351
|
+
The table records the host `route` and the remote expose `spec` (omit `./` and do not repeat the remote name); `remotePrefixes` selects the remote. For example, `/shop/home`, `spec: 'pages/Home'` and `remotePrefixes: { '/shop': 'shop' }` resolve to `shop/pages/Home`. Vue can use KeepAlive for component state; React has no equivalent keep-alive promise here.
|
|
352
|
+
|
|
353
|
+
See [page API](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#pages) and [page demo](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/demos/pages-cli).
|
|
372
354
|
|
|
373
|
-
|
|
355
|
+
## Build and deploy
|
|
374
356
|
|
|
375
|
-
|
|
357
|
+
Build each application separately with its own `npm run build`. The remote produces `fulgurjs-remoteEntry.js` and `fulgurjs-manifest.json` by default. The host locates them through `prod`.
|
|
376
358
|
|
|
377
|
-
|
|
378
|
-
- `window.__FULGURJS_INFO__` — per-remote status/latency/errors + `errors` log
|
|
379
|
-
- `DEBUG=fulgurjs:*` — controlled pipeline diagnostics (off by default)
|
|
380
|
-
- Runtime diagnostics are emitted in Chinese by design (language policy); codes are stable identifiers listed below
|
|
359
|
+
Check these settings:
|
|
381
360
|
|
|
382
|
-
|
|
361
|
+
- Remote deployment `/remote-vue/` → remote Vite `base: '/remote-vue/'` and host `prod: '/remote-vue'`.
|
|
362
|
+
- HTML, remoteEntry and manifest use `Cache-Control: no-cache`; content-hashed chunks can use long-lived caching.
|
|
363
|
+
- SPA routes support refresh; missing resource URLs return 404 rather than HTML.
|
|
364
|
+
- Cross-origin deployments need production CORS headers; dev settings do not configure the production server.
|
|
365
|
+
- Keep chunks still referenced by old pages available during releases, or use a deployment flow that avoids mixed versions.
|
|
383
366
|
|
|
384
|
-
|
|
367
|
+
Deployment examples: [Vue](https://github.com/chenmingye/fulgurjs-federation/blob/master/examples/templates/vue-vue/README.md) / [React](https://github.com/chenmingye/fulgurjs-federation/blob/master/examples/templates/react-react/README.md).
|
|
368
|
+
|
|
369
|
+
## Handle failures
|
|
370
|
+
|
|
371
|
+
| Symptom | Check | Recovery |
|
|
385
372
|
|---|---|---|
|
|
386
|
-
|
|
|
387
|
-
|
|
|
388
|
-
|
|
|
389
|
-
| |
|
|
390
|
-
| |
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
| | `MFU-002` | remoteEntry self-reported name mismatch |
|
|
413
|
-
| | `MFU-003` | strictVersion requirement not satisfied |
|
|
414
|
-
| | `MFU-004` | shared module missing with no local fallback |
|
|
415
|
-
| | `MFU-005` | same container re-initialized with a different share scope |
|
|
416
|
-
| | `MFU-006` | requested module not exposed by the remote |
|
|
417
|
-
| | `MFU-007` | preload failed (non-blocking) |
|
|
418
|
-
| | `MFU-008` | unknown remote |
|
|
419
|
-
| | `MFU-009` | loaded module has no exports at all |
|
|
420
|
-
| | `MFU-010` | reused singleton version doesn't satisfy the consumer requirement (warn-once) |
|
|
421
|
-
| | `MFU-011` | setup entry export shape invalid |
|
|
422
|
-
| | `MFU-012` | setup/onSession threw (retryable; only the failed stage resets) |
|
|
423
|
-
| | `MFU-013` | onSession declared but host sessionKey missing |
|
|
424
|
-
| | `MFU-014` | setup/onSession synchronously re-loading the same remote (deadlock guard) |
|
|
425
|
-
| | `MFU-015` | bridge contract invalid (`./bridge` default export missing non-function mount/unmount; fix points to `defineBridgeApp`) |
|
|
426
|
-
| | `MFU-016` | bridge preparation or lifecycle failure (`details.phase` = getContext/mount/unmount; cause keeps the sub-app's original error) |
|
|
427
|
-
| | `MFU-017` | bridge session mismatch (controlled sessionKey vs AppContext / illegal value / page-level single-session conflict) |
|
|
428
|
-
| MFU | `MFU-030` | Bridge URL-sync config invalid / prefix conflict (illegal basePath: empty, root, query/hash/wildcard; overlapping active prefixes) |
|
|
429
|
-
| MFU | `MFU-031` | Bridge routing protocol missing / channel destroyed (sub-app not declared with `{ routing: true }`; disposed channel reused) |
|
|
430
|
-
| MFU | `MFU-032` | Bridge illegal navigation (target escaping its own prefix, illegal `go` argument, request on a dead channel) |
|
|
431
|
-
| MFU | `MFU-033` | Bridge routing preparation/sync failed (redirect limit or navigation exception, chain/cause attached; no silent fallback to memory) |
|
|
432
|
-
| CC | `CC-001` | AppContext required key missing (got/expected/example) |
|
|
433
|
-
| | `CC-002` | runtime singleton unavailable (standalone remote page) |
|
|
434
|
-
|
|
435
|
-
## 12. Boundaries (explicitly not supported)
|
|
436
|
-
|
|
437
|
-
- Support covers **browser-client** federation for Vue 3 and React 18–19. Not supported: SSR, React Server Components, Next.js full-stack, React Native, Node-side remote loading. **Cross-framework boundary (5.3.0+)**: sub-app-level embedding is supported (§8.7 `/bridge`); direct component-level Vue↔React rendering in one tree is not (that is the product of framework-conversion libraries). Pure single-framework projects keep zero cross-dependency
|
|
438
|
-
- **Bridge isolation boundary (declared honestly in §8.7)**: bridging isolates only the mount/unmount edge of the two component trees — no browser realm isolation. Remote global CSS, `body`/`html` styles, global variables, and DOM rendered outside the container via React Portal / Vue Teleport still affect the host; `unmount` cannot revoke CSS the browser already loaded. Sub-app internal errors do not bubble into host error boundaries (cross-root). Sub-app routing defaults to memory mode; explicit URL sync exists since 5.4.0 (§8.8) — when it is not enabled, refreshing does not restore the sub-app's internal path
|
|
439
|
-
- React side does not promise component keep-alive (`keepAliveNames` is Vue-only); re-opened pages still reuse downloaded modules
|
|
440
|
-
- Cross-origin Fast Refresh: remote React components update via the remote dev server's HMR push; after a cold start the first round often needs a host refresh — component-state retention across the federation boundary is not promised
|
|
441
|
-
- Not compatible with originjs `virtual:__federation__` legacy imports
|
|
442
|
-
- No browser DevTools extension (the `window.__FULGURJS_*` surfaces serve debugging)
|
|
443
|
-
|
|
444
|
-
## 13. Documentation & examples
|
|
445
|
-
|
|
446
|
-
- [Migration guide (Chinese)](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/迁移指南.md) — a real qiankun → federation migration (seven steps + acceptance checklist)
|
|
447
|
-
- [webpack MF comparison & gaps (Chinese)](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/webpack-mf-对照与缺口.md)
|
|
448
|
-
- [Sandbox boundary audit (Chinese)](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/沙箱边界审计.md)
|
|
449
|
-
- [`DESIGN.md`](https://github.com/chenmingye/fulgurjs-federation/blob/master/DESIGN.md) — architecture and alignment tables
|
|
450
|
-
- Examples: [`examples/vue/{host,remote}`](./examples) + [`examples/react/{host,remote}`](./examples) + [`examples/bridge/*`](./examples) — copy-and-run projects, registry-installable (see the examples entry page)
|
|
451
|
-
|
|
452
|
-
## 14. Development & testing
|
|
373
|
+
| Remote unavailable | Server, address, CORS | Timeout/retry/error UI; optional backup entry or fallback module |
|
|
374
|
+
| Module missing | remotes name and exposes key | Fix the name and retry |
|
|
375
|
+
| Shared version incompatible | Installed versions, requiredVersion, strictVersion, scope | Align or isolate versions |
|
|
376
|
+
| Static dependency remains failed after service recovery | Browser may retain the failed dependency URL | User-initiated refresh preserves the current address |
|
|
377
|
+
| Child unmount fails | Child cleanup, timers and subscriptions | Container stays blocked; refresh and fix cleanup |
|
|
378
|
+
|
|
379
|
+
`remoteComponent` and bridge components provide default error UI. Direct `loadRemote` calls and React `useLoadRemote` require application error handling. An explicit `fallbackModule` does not repair the original remote.
|
|
380
|
+
|
|
381
|
+
Errors include a code, cause and fix. See [error codes](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#error-codes).
|
|
382
|
+
|
|
383
|
+
## Vite 8 and support boundaries
|
|
384
|
+
|
|
385
|
+
**Supports Vite 8 development and production. The earlier large-application startup hang has been fixed and relevant regression tests pass.**
|
|
386
|
+
|
|
387
|
+
Two practical details:
|
|
388
|
+
|
|
389
|
+
- A first dev visit may reload while Vite prepares newly discovered dependencies. Wait for optimization before judging stable behavior. This is not a production behavior on every visit.
|
|
390
|
+
- Some shared scenarios fetch an unused local library copy. One singleton scope still uses one instance; explicitly isolated React 18/19 scopes may use one each. Downloaded file count and active instance count are different.
|
|
391
|
+
|
|
392
|
+
Not provided: SSR/RSC, Node-side federation, React Native, automatic JS/CSS isolation, webpack `script/var` artifact interoperability, component-type conversion, automatic multi-level bridge routing proxies or cross-window route sync. Global CSS/variables can affect the host; children need their own internal error handling.
|
|
393
|
+
|
|
394
|
+
See the [capability comparison](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/webpack-mf-对照与缺口.md) for detailed boundaries and differences from webpack.
|
|
395
|
+
|
|
396
|
+
## Debugging, types and CLI
|
|
397
|
+
|
|
398
|
+
Run in the application directory:
|
|
453
399
|
|
|
454
400
|
```bash
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
bash e2e/scripts/prod-setup.sh # build all fixtures + isolated NGINX
|
|
401
|
+
# No existing project: create a complete project from a template (see "Starting fresh")
|
|
402
|
+
npx @fulgurjs/federation create
|
|
403
|
+
|
|
404
|
+
# Existing project: generate a federation config starter file
|
|
405
|
+
npx fulgurjs init # --template <path> sets the output path (a path, not a template id)
|
|
406
|
+
npx fulgurjs explain
|
|
407
|
+
|
|
408
|
+
# Optional: validate a configured host page table
|
|
409
|
+
npx fulgurjs check-pages --site http://localhost:5173
|
|
410
|
+
|
|
411
|
+
# After deployment under /remote-vue/, substitute your actual site:
|
|
412
|
+
npx fulgurjs doctor --base https://your-site.example --apps remote-vue
|
|
468
413
|
```
|
|
469
414
|
|
|
470
|
-
|
|
415
|
+
For `doctor`, `--base` is the site URL and `--apps` lists **deployment subdirectories** (a remote deployed under `/remote-vue/` is `remote-vue`): the example checks `https://your-site.example/remote-vue/`. It does not infer a different development port from a container name.
|
|
416
|
+
|
|
417
|
+
`init` creates a federation config template, not a full application, router or Nginx configuration (use `create` for a new complete project). `check-pages` compares the page table with remote exposes; an unreachable remote is reported as unverified.
|
|
418
|
+
|
|
419
|
+
Remote dev types are generated by default. Accessible source provides more precise mapping; inaccessible source produces `any` declarations without precise checks/completion. Set `dts: false` to disable generation. See the reference for details.
|
|
420
|
+
|
|
421
|
+
Advanced diagnostics use `window.__FULGURJS_SCOPE__`, `window.__FULGURJS_INFO__` and `FULGURJS_DEBUG`. Normal integration does not require editing these objects.
|
|
422
|
+
|
|
423
|
+
## API reference
|
|
424
|
+
|
|
425
|
+
Use the current reference rather than guessing signatures from old task documents:
|
|
426
|
+
|
|
427
|
+
- [Plugin options and defaults](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#plugin-options)
|
|
428
|
+
- [Runtime loading, registration and hooks](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#runtime)
|
|
429
|
+
- [Bridge props, sessions and cleanup](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#bridge)
|
|
430
|
+
- [URL sync and navigation](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.en.md#url-sync)
|
|
431
|
+
- [Chinese API reference](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/API.md)
|
|
432
|
+
|
|
433
|
+
### When an AI implements your integration
|
|
434
|
+
|
|
435
|
+
Specify the framework, whether you need a component or sub-app, remote URLs/expose names, and whether login switching or URL sync is required. Have it read the guide and relevant API section first, preserve the existing Vite configuration, check installed versions and use the correct browser entry. It should not invent configuration fields. Verify mounting, interaction and error handling; URL sync also needs deep-link refresh, history and cancellation checks.
|
|
436
|
+
|
|
437
|
+
## Documentation
|
|
438
|
+
|
|
439
|
+
- [Demo catalog](https://github.com/chenmingye/fulgurjs-federation/blob/master/examples/demos/README.md): setup and runnable scenarios.
|
|
440
|
+
- [Copy-and-run templates](https://github.com/chenmingye/fulgurjs-federation/tree/master/examples/templates): five pnpm-workspace examples/templates (Vue×Vue, React×React, both cross-framework bridge directions, and a full showcase). Copy a folder, then `pnpm install && pnpm dev`.
|
|
441
|
+
- [Migration guide](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/迁移指南.md).
|
|
442
|
+
- [CHANGELOG](https://github.com/chenmingye/fulgurjs-federation/blob/master/CHANGELOG.md): changes and migration requirements.
|
|
443
|
+
- [Acceptance records](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/整夜全量验收报告-20261004.md): overnight acceptance on two real MES business projects (fresh SVN copies), covering dev, production, fault recovery and HMR, plus production-build notes for large Vite 6 apps (that round required disabling `manualChunks`; **fixed in 5.8.0 — keep your own `manualChunks`, shared bodies are isolated into `fulgurjs-provider-*` chunks automatically**). Historical record: [20261002 demo acceptance](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/完整Demo展示与全面复测-验收报告-20261002.md) — historical results are not a substitute for testing your application.
|
|
444
|
+
|
|
445
|
+
## Development and testing
|
|
446
|
+
|
|
447
|
+
These commands develop **this plugin repository**; ordinary consumers do not need them:
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
pnpm --dir packages/plugin install
|
|
451
|
+
pnpm --dir packages/plugin build
|
|
452
|
+
pnpm test:unit
|
|
453
|
+
```
|
|
471
454
|
|
|
472
|
-
|
|
455
|
+
See [CONTRIBUTING](https://github.com/chenmingye/fulgurjs-federation/blob/master/CONTRIBUTING.md) for fixture installation and browser test prerequisites. CI checks builds, types, unit tests, installed packages and browser scenarios across multiple Vite versions. Counts come from the corresponding run.
|
|
473
456
|
|
|
474
457
|
## License
|
|
475
458
|
|
|
476
|
-
[MIT](
|
|
459
|
+
[MIT](LICENSE) © chenmingye (Jason)
|