@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.
- package/CHANGELOG.md +17 -0
- package/README.en.md +7 -5
- package/README.md +14 -12
- package/dist/context.cjs +2 -2
- package/dist/context.js +2 -2
- package/dist/index.cjs +141 -48
- package/dist/index.js +141 -48
- package/dist/react-adapter.cjs +32 -1
- package/dist/react-adapter.d.cts +1 -1
- package/dist/react-adapter.d.ts +1 -1
- package/dist/react-adapter.js +32 -1
- package/dist/react.d.ts +2 -2
- package/dist/runtime-entry.d.ts +2 -2
- package/dist/runtime.js +7 -7
- package/dist/vue-adapter.cjs +99 -15
- package/dist/vue-adapter.d.cts +1 -1
- package/dist/vue-adapter.d.ts +1 -1
- package/dist/vue-adapter.js +100 -16
- package/examples/README.en.md +47 -0
- package/examples/README.md +40 -18
- package/examples/react/README.md +83 -0
- package/examples/react/host/README.md +49 -0
- package/examples/react/host/fulgurjs.config.ts +31 -0
- package/examples/{react-remote → react/host}/index.html +2 -1
- package/examples/react/host/package-lock.json +2381 -0
- package/examples/react/host/package.json +24 -0
- package/examples/react/host/src/App.tsx +19 -0
- package/examples/react/host/src/main.tsx +33 -0
- package/examples/react/host/src/pages/UtilsDemo.tsx +32 -0
- package/examples/react/host/src/remotePages.tsx +16 -0
- package/examples/{react-remote → react/host}/tsconfig.json +2 -3
- package/examples/{react-remote → react/host}/vite.config.ts +2 -2
- package/examples/react/remote/README.md +47 -0
- package/examples/react/remote/fulgurjs.config.ts +20 -0
- package/examples/{react-host → react/remote}/index.html +2 -1
- package/examples/react/remote/package-lock.json +2323 -0
- package/examples/react/remote/package.json +23 -0
- package/examples/react/remote/src/App.tsx +16 -0
- package/examples/react/remote/src/exposes/ClickButton.tsx +15 -0
- package/examples/react/remote/src/exposes/pages/DetailPage.tsx +10 -0
- package/examples/react/remote/src/exposes/pages/HomePage.tsx +12 -0
- package/examples/react/remote/src/exposes/utils.ts +10 -0
- package/examples/react/remote/src/main.tsx +11 -0
- package/examples/{react-host → react/remote}/tsconfig.json +3 -4
- package/examples/{react-host → react/remote}/vite.config.ts +2 -2
- package/examples/vue/README.md +85 -0
- package/examples/vue/host/README.md +50 -0
- package/examples/vue/host/fulgurjs.config.ts +30 -0
- package/examples/vue/host/index.html +12 -0
- package/examples/vue/host/package-lock.json +1855 -0
- package/examples/vue/host/package.json +21 -0
- package/examples/vue/host/src/App.vue +12 -0
- package/examples/vue/host/src/main.ts +44 -0
- package/examples/vue/host/src/pages/HomePage.vue +16 -0
- package/examples/vue/host/src/pages/UtilsDemo.vue +45 -0
- package/examples/vue/host/tsconfig.json +13 -0
- package/examples/vue/host/vite.config.ts +8 -0
- package/examples/vue/remote/README.md +47 -0
- package/examples/vue/remote/fulgurjs.config.ts +20 -0
- package/examples/vue/remote/index.html +12 -0
- package/examples/vue/remote/package-lock.json +1833 -0
- package/examples/vue/remote/package.json +20 -0
- package/examples/vue/remote/src/App.vue +16 -0
- package/examples/vue/remote/src/exposes/ClickButton.vue +16 -0
- package/examples/vue/remote/src/exposes/pages/DetailPage.vue +14 -0
- package/examples/vue/remote/src/exposes/pages/HomePage.vue +11 -0
- package/examples/vue/remote/src/exposes/utils.ts +10 -0
- package/examples/vue/remote/src/main.ts +6 -0
- package/examples/vue/remote/tsconfig.json +13 -0
- package/examples/vue/remote/vite.config.ts +8 -0
- package/package.json +2 -2
- package/examples/host/fulgurjs.config.ts +0 -26
- package/examples/react-host/README.md +0 -28
- package/examples/react-host/fulgurjs.config.ts +0 -19
- package/examples/react-host/package.json +0 -23
- package/examples/react-host/src/App.tsx +0 -66
- package/examples/react-host/src/federation/pages.data.ts +0 -21
- package/examples/react-host/src/main.tsx +0 -8
- package/examples/react-remote/fulgurjs.config.ts +0 -17
- package/examples/react-remote/package.json +0 -22
- package/examples/react-remote/src/Button.tsx +0 -15
- package/examples/react-remote/src/main.tsx +0 -6
- package/examples/react-remote/src/pages/Detail.tsx +0 -10
- package/examples/react-remote/src/pages/Home.tsx +0 -14
- package/examples/react-remote/src/utils.ts +0 -3
- package/examples/remote-a/fulgurjs.config.ts +0 -24
- package/examples/remote-a/src/views/Detail.vue +0 -3
- package/examples/remote-a/src/views/Home.vue +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.2.0
|
|
4
|
+
|
|
5
|
+
- **修复:Vue 默认错误占位没有可操作的恢复入口(D1)**——默认占位新增两个用户操作:「重试加载」(同页重建加载链,重跑真实 loader 含 beforeLoad;Vue 的 defineAsyncComponent userRetry 在 userFail 后永久失效,故恢复由占位组件自身承载,成功后原位渲染业务组件并透传 attrs)与「刷新页面重试」(用户点击才整页刷新,保留 pathname/query/hash,绝不自动触发)。`remoteComponent` 与 `createHostPages().component()` 两条路径一致;自定义 `errorComponent` 契约不变(完全接管、不注入按钮);KeepAlive 组件树形状与 5.1.x 完全一致。
|
|
6
|
+
- **修复:React 默认错误占位补齐刷新恢复(D1/D2)**——load 阶段默认占位同样提供「重试加载 / 刷新页面重试」双操作(渲染阶段错误仍只提供「重试加载」,文案明确区分网络与远程代码错误)。
|
|
7
|
+
- **修复:生产静态子依赖失败的用户恢复闭环(D2)**——浏览器 module map 缓存静态子依赖失败(同 URL 再 import 直接拒绝),同页重试无法穿透;默认占位的「刷新页面重试」给出确定的整页恢复路径。`prod B3c` 由「两种结果都能 PASS」改写为确定性门禁:占位双操作可见 → 同页重试(记录结果)→ 产品按钮触发导航(跨刷新标记证明,非测试脚本 reload)→ 目标业务页面真实恢复;新增 Vue 静态依赖生产用例(remote-a 静态依赖链 fixture + host-vue 页面)。
|
|
8
|
+
- **修复:React 跨应用开发更新真实自动传播(D3)**——根因:react-refresh 运行时状态(helpersByRendererID/pending 队列)为模块私有,宿主页内第二份副本(远程 origin)刷新空转。修复:宿主 preamble 后注入发布脚本把页面级 react-refresh 单例发布到 globalThis;远程组件的 /@react-refresh 导入改写到插件 shim(dev),shim 优先委托页面单例、standalone 回退本源实例。R11 重写为「5 轮冷启动 × 3 次修改」零人工刷新热更新保活门禁 + R11b 普通 TS 依赖传播门禁(挂载宿主实际看到新值)。
|
|
9
|
+
- **修复:Vite 5.x 双 client 错误覆盖层 IllegalConstructor(D4)**——Vite 5 客户端对 `vite-error-overlay` 的 define 有注册守卫,双 client 场景第二份客户端的本地 ErrorOverlay 类未注册,按 HTML 规范 new 未注册 HTMLElement 子类抛 IllegalConstructor,远程编译错误覆盖层无法显示。修复:把 Vite ≥6 的注册表构造修法前移到 Vite 5 客户端代码(fulgurjs:dev-client-compat,不改已安装 Vite 源码);fault.spec 的 5.1.4 版本门控 skip 移除,支持矩阵内该用例全部真实执行(Vite 5.1.4 本地实测通过)。
|
|
10
|
+
- **示例重构(D7)**:examples 按框架分组为 `examples/vue/{host,remote}`(5214/5213)与 `examples/react/{host,remote}`(5204/5203)四个完整可复制工程(npm + registry 精确正式包 + 独立 fulgurjs.config.ts + 完整入口/源码/README),每对演示远程可点击组件、普通 TS 模块调用、联邦首页/参数详情页、宿主导航懒加载、默认错误恢复;旧 `examples/{host,remote-a,react-host,react-remote}` 目录移除。中英文 examples 总入口与 GitHub 根 README 同步。
|
|
11
|
+
- **文档(D5)**:中英文 README 与恢复/HMR 实际行为对齐;「失败 dynamic import 绝对不会再次访问网络」等表述限定到真实浏览器边界;支持矩阵与恢复操作口径统一。
|
|
12
|
+
|
|
13
|
+
## 5.1.4
|
|
14
|
+
|
|
15
|
+
- 修复类型生成的数组 extends、目录 references、独立 baseUrl 继承及继承 include 上下文识别;多个应用 paths 接管不一致时保留可解析声明并提示统一配置。
|
|
16
|
+
- setup/onSession 失败包装保留原始 Error.cause,中文 MFU-012 与重试语义不变。
|
|
17
|
+
- 增加开发/生产共用 React 浏览器契约:冷加载、多实例、真实慢快请求竞态、双向跨框架模块及生命周期失败恢复。
|
|
18
|
+
- 忽略 examples 构建与自动类型产物;完整验收结果在发版后的独立报告记录。
|
|
19
|
+
|
|
3
20
|
## 5.1.3(2026-09-29)
|
|
4
21
|
|
|
5
22
|
- **修复:TS 应用配置上下文识别(dev 类型双轨判定)**——宽松声明是否让位于精确轨,此前扫描根目录全部 `tsconfig*.json`(仅排除 `tsconfig.node.json`),任何一份无关配置(如 `tsconfig.test.json`)出现 `<remote>/*` paths 即误判「应用已接管」,抑制应用导入所需的 ambient 声明(导入 TS2307)。现在按真实 TS 上下文判定:主配置选择(`tsconfig.json`,或唯一/唯一覆盖应用源码的 `tsconfig*.json`——含只有 `tsconfig.typecheck.json` 的工程)+ `references` 链上 include 覆盖应用源码/类型输出目录的子项目(solution 型 `files: []` 配置自身不判定,不再按文件名排除);`extends` 链 paths 继承,paths 目标与 baseUrl 按声明所在配置的目录解析。无法唯一确定上下文时安全回退(生成默认宽松声明,导入可解析)。真实 tsc 编译回归:无关测试配置不抑制 ambient;应用接管后精确轨拒绝错误 props。
|
package/README.en.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
| semantic parity | 100% | incomplete (version negotiation / singleton / fault tolerance often missing) | ✅ aligned clause-by-clause with webpack semantics, e2e-verified |
|
|
19
19
|
| **UMD / CJS-only deps** | DIY | **commonly unusable** | ✅ automatic (dep-optimizer externalization + build-time require shims) |
|
|
20
20
|
| remote load failures | raw errors | usually missing | ✅ retry / circuit breaker / timeout built in + explicit `fallbackModule` degradation |
|
|
21
|
-
| failure recovery | reload the page | usually missing | ✅
|
|
21
|
+
| failure recovery | reload the page | usually missing | ✅ built-in placeholders offer **Retry load** (in-page; failed URLs are varied to penetrate the browser's failed-import cache) and **Refresh page to retry** (a user-initiated full reload for failures the browser caches beyond in-page reach) |
|
|
22
22
|
| runtime size | ~40KB+ | varies | **gzip < 9KB** (framework-neutral core; adapters are separate) |
|
|
23
23
|
| misconfiguration | hard to debug | cryptic | three-part diagnostics: symptom / cause / fix |
|
|
24
24
|
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- **Automatic async boundaries** — top-level await injected automatically (es2022+); no webpack-style manual `import('./bootstrap')`
|
|
30
30
|
- **Stable artifacts** — remoteEntry keeps a fixed filename (content changes every build → **must be `no-cache`**; only content-hashed chunks may be cached long); `fulgurjs-manifest.json` asset manifest; one chunk per expose
|
|
31
31
|
- **Fault tolerance (webpack MF 2.0 errorLoadRemote aligned)** — retry / circuit breaker / timeout built in; `loadRemote(spec, { retries, fallbackModule })` per-call overrides; on failure the fallback module is returned and the error event is still emitted (**never silent**; without `fallbackModule` the error re-throws)
|
|
32
|
-
- **Real failure recovery** —
|
|
32
|
+
- **Real failure recovery** — Chromium/Firefox/Safari cache failed dynamic imports per URL, so re-importing the same URL rejects without hitting the network again (verified per browser in this repo's e2e; see MDN import() for the underlying semantics). After a real failure the runtime varies the URL (`fulgurjs_retry=N`) across remote-entry loading, dev container loaders and the prod remoteEntry, so "service recovered → click Retry load" genuinely re-fetches. Successful modules are never re-requested with a varied URL — module identity and singletons are preserved; concurrent failures advance exactly one retry generation (no module-instance split); repeated access to loaded modules issues zero extra requests. **Known boundary**: a failed **static dependency** chunk of an expose cannot recover in-page (the browser caches the dependency URL's failure). The built-in placeholder therefore also offers **Refresh page to retry** — a user-initiated full reload that keeps the current URL (never automatic, no reload loops) — and that is the supported recovery path for this case; the plugin deliberately does not rewrite the whole site dependency graph to work around it
|
|
33
33
|
- **Enhancements** — dev type generation (dual-track, see §8.6), manifest-driven `preloadRemote()`, runtime plugin hooks (`beforeLoadRemote` / `afterLoadRemote` / `onRemoteError` / `resolveShare`)
|
|
34
34
|
- **Full HMR chain** — remote edits propagate to the host page: component hot swap, state retention, error overlay and recovery
|
|
35
35
|
- **Zero-silent-failure discipline** — config problems fail at startup with three-part diagnostics; federation failures throw explicitly (error code + actionable fix); no silent fallback paths
|
|
@@ -115,7 +115,7 @@ const RemoteHome = hp.component('remote-react/pages/home')
|
|
|
115
115
|
|
|
116
116
|
**Data flow for host state (context):** the host provides context (`provideAppContext`, including a non-sensitive `sessionKey`) and then triggers its own re-render (React state / router). Mounted remote components and hooks observe the new `sessionKey` on that render and re-run their load lifecycle — A→B account switching works on the same mounted instance without remounting. `AppContext` is a plain snapshot: the plugin does not subscribe to it reactively; the host must trigger the render. `beforeLoad` (page tables) runs before every actual load attempt to refresh context. Logout: call `clearAppContext()` before unmounting authed UI.
|
|
117
117
|
|
|
118
|
-
Runnable examples: [`examples/
|
|
118
|
+
Runnable examples: [`examples/vue/{host,remote}`](./examples) and [`examples/react/{host,remote}`](./examples) — four complete copy-and-run projects installed from the npm registry (see the examples entry page). In-repo e2e fixtures: `fixtures/host-react` / `fixtures/remote-react`.
|
|
119
119
|
|
|
120
120
|
## 6. Quick start — Vue
|
|
121
121
|
|
|
@@ -177,7 +177,7 @@ Standalone page-level boundary. Props: `children`, `fallback` (node or `({ error
|
|
|
177
177
|
- Data options (identical to Vue): `pages`, `remotePrefixes`, `deriveSpec`, `schema`, `strict`, `base`
|
|
178
178
|
- Display options (same semantics as `remoteComponent`): `fallback`, `error`, `retries`, `timeout`; plus `beforeLoad: () => void | Promise<void>` — runs before **every actual load attempt** (including retries) so the host can refresh context; never at table creation
|
|
179
179
|
- `component<P>(spec)` returns a React component type; the component cache is keyed by spec + login generation (rebuilt only on a new non-empty `sessionKey`; logout → `undefined` does not rebuild). Module-level caching of `component(spec)` results is supported — mounted pages still follow session changes
|
|
180
|
-
- 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
|
|
180
|
+
- 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)
|
|
181
181
|
- 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
|
|
182
182
|
|
|
183
183
|
### 8.2 Runtime API — `@fulgurjs/federation/runtime` (Vue apps) and common functions on `/react`
|
|
@@ -251,6 +251,8 @@ export async function onSession(ctx: { appContext: any; sessionKey: string; sign
|
|
|
251
251
|
|
|
252
252
|
- Zero config: ambient declarations per expose — imports resolve, exports typed `any`; setup entry never generates declarations
|
|
253
253
|
- 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
|
|
254
|
+
|
|
255
|
+
Type generation supports string or array `extends` (later entries override earlier entries) and directory `references`; inherited paths retain their declaring directory. `baseUrl` and `paths` inherit independently. If application contexts disagree on remote `paths`, the plugin keeps loose declarations and reports a diagnostic; align application mappings to enable precise types. Lifecycle errors (`MFU-012`) retain the original setup/onSession exception in `cause`.
|
|
254
256
|
- `devFsRoot: false` or unreachable source: degrades to resolvable `any` declarations and cleans stale precise-track files (precise → degrade → restore cycles compile cleanly)
|
|
255
257
|
- `dts: false` stops generation without deleting existing output; `dts.dir` relocates; `mode: 'shim'` gives loose IDE-clean placeholders
|
|
256
258
|
- Precise track requires the host and remote to share a filesystem (same-machine dev); verified bounds: React 18.0.0–19.x with matching @types
|
|
@@ -333,7 +335,7 @@ Lazy-loading measurement layers: ① nothing until first render of a remote comp
|
|
|
333
335
|
- [webpack MF comparison & gaps (Chinese)](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/webpack-mf-对照与缺口.md)
|
|
334
336
|
- [Sandbox boundary audit (Chinese)](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/沙箱边界审计.md)
|
|
335
337
|
- [`DESIGN.md`](https://github.com/chenmingye/fulgurjs-federation/blob/master/DESIGN.md) — architecture and alignment tables
|
|
336
|
-
- Examples: [`examples/
|
|
338
|
+
- Examples: [`examples/vue/{host,remote}`](./examples) + [`examples/react/{host,remote}`](./examples) — four complete copy-and-run projects, registry-installable (see the examples entry page)
|
|
337
339
|
|
|
338
340
|
## 14. Development & testing
|
|
339
341
|
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- **UMD / CJS-only 依赖开箱即用**:element-plus、avue 等只有 UMD/CJS 产物的依赖直接进 `optimizeDeps.include` 即可——dev 期插件自动把预构建产物内的 shared 键改道协商门面;build 期自动把 CJS `require(<shared>)` 重定向到垫片,双运行时免疫
|
|
30
30
|
- **自动异步边界**:top-level await 自动注入(es2022+),无需 webpack 式手工 `import('./bootstrap')`
|
|
31
31
|
- **稳定产物**:remoteEntry 固定文件名便于稳定引用(入口内容每次构建变,**必须 no-cache**——只有带内容哈希的 chunk 才可长缓存);`fulgurjs-manifest.json` 资源清单;expose 独立 chunk
|
|
32
|
-
- **容错(对齐 webpack MF 2.0 errorLoadRemote)**:加载重试 / 熔断 / 超时内置;`loadRemote(spec, { retries, fallbackModule })` 单次调用级覆盖——失败时返回 fallback
|
|
32
|
+
- **容错(对齐 webpack MF 2.0 errorLoadRemote)**:加载重试 / 熔断 / 超时内置;`loadRemote(spec, { retries, fallbackModule })` 单次调用级覆盖——失败时返回 fallback 模块,错误事件仍显式发出(**绝不静默兜底**,不传则照旧抛错)。组件级默认错误占位提供用户恢复操作:**重试加载**(同页重试,失败后换 URL 穿透浏览器失败缓存)与**刷新页面重试**(用户点击才整页刷新,覆盖浏览器失败缓存无法同页穿透的静态子依赖场景)
|
|
33
33
|
- **增强能力**:dts 类型直连(dev 补全直达 remote 源码)、`preloadRemote()` manifest 驱动精确预载、runtimePlugins 钩子
|
|
34
34
|
- **HMR 全链路**:remote 改动 → host 页面热更,L1 组件热替换 / L2 状态保留 / L3 错误覆盖与恢复
|
|
35
35
|
- **零报错纪律**:配置问题启动瞬间三段式报错;联邦失败显式抛错(错误码 + 可执行修复建议),**无任何静默兜底路径**
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
- **远程初始化生命周期(可选)**:`federation({ setup })` 显式声明初始化入口——默认导出 `setup(context)` 应用级执行一次、可选具名导出 `onSession(context)` 按宿主 `sessionKey` 去重执行(换账号/重登自动重跑,退出 `clearAppContext` 清理会话状态);失败显式报错可重试(`MFU-011~014`),`preloadRemote`/`getContainer` 无副作用。不配置 `setup` 时零行为零体积
|
|
38
38
|
- **宿主页面适配器(可选)**:`createHostPages({ pages, remotePrefixes, ... })`——一份页面表供宿主路由与布局共用;URL 解析(含 base 剥离)、最长前缀远程归属、`definePages` R1–R5 校验、异步组件缓存(会话切换自动重建)、骨架屏/错误占位、保活名称内置
|
|
39
39
|
- **跨应用传值与方法引用**:`@fulgurjs/federation/runtime` 导出 `provideAppContext` / `getAppContext` / `requireAppContext` / `clearAppContext`(缺键 `CC-001` 三段式、独立直开远程页 `CC-002` 显式)。宿主桥写入页面级单例(user/getToken/store/hostApp/locale/sessionKey/events 标准字段 + 项目扩展位),远程 setup/onSession 显式校验消费;方法引用两条通道 = context 携带函数引用(热路径直调)+ exposes 方法模块 `loadRemote('remote/api')`(低频重逻辑)。数据语义 = 传输层快照 + 函数引用,非响应式(与乾坤 props 同语义;"实时"靠函数引用拉取 / 宿主 pinia 共享承担,同页换账号由 onSession 会话同步承担,不依赖页面刷新)
|
|
40
|
-
- **Vue 直渲染**:`remoteComponent('remote/X')`(`@fulgurjs/federation/runtime` 导出)——`defineAsyncComponent + loadRemote`
|
|
41
|
-
- **React 完整支持(浏览器端)**:`@fulgurjs/federation/react` 独立入口——`remoteComponent`(含 Suspense
|
|
40
|
+
- **Vue 直渲染**:`remoteComponent('remote/X')`(`@fulgurjs/federation/runtime` 导出)——`defineAsyncComponent + loadRemote` 的标准封装,加载失败显式错误占位(错误码+根因+修法+**重试加载/刷新页面重试**),runtime.js 零框架依赖零体积增量
|
|
41
|
+
- **React 完整支持(浏览器端)**:`@fulgurjs/federation/react` 独立入口——`remoteComponent`(含 Suspense 占位/错误占位/**重试加载+刷新页面重试**,不用 React.lazy 的失败缓存陷阱)、`useLoadRemote`(代次守卫的模块 hook)、`RemoteErrorBoundary`(页面级兜底)、`createReactHostPages`(与 Vue 同源页面表与 R1–R5 校验);共享 `react`/`react-dom` singleton 协商,Hooks/StrictMode/Context 跨端同实例(dev 预构建外部化 + prod CJS 垫片自动处理 `react/jsx-runtime`、`react-dom/client` 子路径);纯 React 项目零 Vue 依赖、纯 Vue 项目零 React 依赖
|
|
42
42
|
- **CSP 友好**:原生 ESM 加载路径全程无 `eval` / `new Function`,可在严格 CSP(无 `unsafe-eval`)下运行
|
|
43
43
|
- **全链路错误码体系(41 码)**:CFG/DEV/BLD/MFU/CC 五段 + 手册 §6 码表防漂移校验
|
|
44
44
|
|
|
@@ -102,7 +102,7 @@ const hp = createReactHostPages({ pages, remotePrefixes, schema: remoteSchema })
|
|
|
102
102
|
const RemoteHome = hp.component('remote-react/pages/home')
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
完整可复制工程见 [`examples/react
|
|
105
|
+
完整可复制工程见 [`examples/react/host`](./examples/react/host)(React 宿主)与 [`examples/react/remote`](./examples/react/remote)(React 远程);Vue 对应 [`examples/vue/host`](./examples/vue/host) + [`examples/vue/remote`](./examples/vue/remote)。API 精确语义(含 timeout/retry/StrictMode/Context/错误恢复)见 [§8.1 React 适配 API](#81-react-适配-api--fulgurjsfederationreact)。
|
|
106
106
|
|
|
107
107
|
## 快速开始:三条接入路径
|
|
108
108
|
|
|
@@ -291,7 +291,7 @@ import { loadRemote, provideAppContext, getAppContext, requireAppContext, clearA
|
|
|
291
291
|
```bash
|
|
292
292
|
# 1) 生成单项目 fulgurjs.config.ts 起步模板(默认导出直接是 federation() 选项;已存在则拒绝,--force 覆盖)
|
|
293
293
|
npx fulgurjs init
|
|
294
|
-
# 样例:examples/remote
|
|
294
|
+
# 样例:examples/vue/remote/fulgurjs.config.ts 与 examples/vue/host/fulgurjs.config.ts(完整可复制工程的联邦声明)
|
|
295
295
|
|
|
296
296
|
# 2) 校验配置并输出接入块:federation(fulgurjsConfig) 两行接法 + 通用核对清单(纯打印,不写文件)
|
|
297
297
|
npx fulgurjs init --config fulgurjs.config.ts
|
|
@@ -682,7 +682,7 @@ const FederatedAmisForm = remoteComponent('demo-host/AmisFormRouterPage', {
|
|
|
682
682
|
| 选项 | 类型 | 默认 | 说明 |
|
|
683
683
|
|---|---|---|---|
|
|
684
684
|
| `loadingComponent` | `Component` | — | 加载期间展示 |
|
|
685
|
-
| `errorComponent` | `Component` | 内置错误占位 | 加载失败展示(Vue 会传入 `error` prop
|
|
685
|
+
| `errorComponent` | `Component` | 内置错误占位 | 加载失败展示(Vue 会传入 `error` prop)。自定义时完全接管展示,插件不再注入恢复按钮;默认占位自带「重试加载 / 刷新页面重试」 |
|
|
686
686
|
| `retries` | `number` | 远程注册值(默认 2) | 透传 `loadRemote` |
|
|
687
687
|
| `delay` | `number` | `200` | 切到 loadingComponent 前的等待(ms) |
|
|
688
688
|
| `timeout` | `number` | — | 超时进错误态(ms);不设由 runtime 容器超时兜底 |
|
|
@@ -690,7 +690,7 @@ const FederatedAmisForm = remoteComponent('demo-host/AmisFormRouterPage', {
|
|
|
690
690
|
语义与边界:
|
|
691
691
|
|
|
692
692
|
- 内部 = `defineAsyncComponent({ loader: () => loadRemote(spec, opts).then(m => m.default ?? m) })`,返回标准 Vue 异步组件,`props`(如 `form-params`)在使用处直接透传;
|
|
693
|
-
- **无任何兜底/降级**(H3 零兜底):加载失败显式进错误态;不传 `errorComponent` 时渲染内置占位(错误码 + 根因 +
|
|
693
|
+
- **无任何兜底/降级**(H3 零兜底):加载失败显式进错误态;不传 `errorComponent` 时渲染内置占位(错误码 + 根因 + 修法 + **重试加载 / 刷新页面重试**),`window` 的 `fulgurjs:error` 事件由 runtime 层照常发出;
|
|
694
694
|
- 模块去重沿用 `loadRemote` 内部 Promise 缓存——同 spec 多组件实例只加载一次容器模块;
|
|
695
695
|
- `vue` 为**可选 peerDependency**(`peerDependenciesMeta.optional`):只使用包根(Vite 插件)时无需安装;应用使用 `/runtime` 时需要安装 Vue,因为该入口导出 `remoteComponent`。内部 `runtime.js` 仍不导入 Vue,体积零增量;
|
|
696
696
|
- 运行时实例经 `globalThis.__FULGURJS_RUNTIME__` 页面级单例复用,与 `@fulgurjs/federation/runtime` 的导入殊途同归,无需额外接线。
|
|
@@ -713,9 +713,9 @@ React 浏览器应用唯一导入点:同时导出通用运行时 API(`loadRe
|
|
|
713
713
|
- 组件导出校验:默认导出(或模块本身)必须是函数组件 / class / `memo` / `forwardRef` 等合法组件类型;字符串、数字、空命名空间显式报错(不渲染空白成功页)
|
|
714
714
|
- `ref` 透传:`forwardRef` 导出可正确接收 ref(React 18/19 实测);普通函数组件传 ref 遵循 React 标准行为
|
|
715
715
|
- 渲染期异常由内置边界捕获并与网络/导出错误**分开记录与展示**(文案区分「加载失败」与「渲染出错」);ErrorBoundary 不捕获事件处理器与任意异步回调异常——这两类错误遵循 React 自身语义
|
|
716
|
-
- 内置默认错误占位包含:错误码(FgError 的 `code`,无码渲染错误显示 `UNKNOWN`)、真实根因 message
|
|
716
|
+
- 内置默认错误占位包含:错误码(FgError 的 `code`,无码渲染错误显示 `UNKNOWN`)、真实根因 message、可执行修法,以及两个恢复操作——**「重试加载」**(同页重建加载链)与**「刷新页面重试」**(仅用户点击才整页刷新,保留当前地址;用于浏览器已缓存模块失败的场景,见下条边界)。渲染阶段错误只提供「重试加载」(错误抛自远程代码本身,刷新无法修复)
|
|
717
717
|
- 失败恢复真实穿透浏览器 ESM 失败缓存:运行时对入口 URL 与容器 expose loader 均在失败后的重试上变更 URL(`fulgurjs_retry=N`),服务恢复后点击重试可真实重新拉取(不是只在 mock 下可恢复)。并发加载同一模块失败后重试只推进一个代次(不会因并发失败产生多个重试 URL 导致模块实例分裂);已成功模块的重复访问零重复网络请求
|
|
718
|
-
- **已知边界**:expose 的**静态依赖** chunk(expose chunk 内 `import` 的普通 chunk)失败后,同页重试不可恢复——浏览器 module map 缓存了该依赖 URL 的失败,重试换 URL 的 expose chunk 重新拉取后其静态 import
|
|
718
|
+
- **已知边界**:expose 的**静态依赖** chunk(expose chunk 内 `import` 的普通 chunk)失败后,同页重试不可恢复——浏览器 module map 缓存了该依赖 URL 的失败,重试换 URL 的 expose chunk 重新拉取后其静态 import 仍命中缓存失败。恢复需整页刷新——默认占位的**「刷新页面重试」**就是这条路径的用户操作(用户点击触发,保留当前地址,永不自动刷新);动态 import 形态的共享依赖不受此限。插件不做全站依赖图递归改写来穿透该限制
|
|
719
719
|
|
|
720
720
|
#### `useLoadRemote<Module>(spec, options?)`
|
|
721
721
|
|
|
@@ -748,6 +748,8 @@ const { data, error, loading, reload } = useLoadRemote<Utils>('remote-react/util
|
|
|
748
748
|
|
|
749
749
|
`@fulgurjs/federation/react` 的 `.tsx`/`.ts` expose 与 Vue 共用同一套 dev 类型生成(目录、`dts:false`、`dts.dir`、setup 过滤、`devFsRoot:false` 降级全部一致),并新增**双轨**形态:零配置时生成可解析的宽松声明(导出为 `any`);在宿主**应用 TS 上下文**(`tsconfig.json` 本身、其 `extends` 链,或其 `references` 指向且 include 覆盖应用源码/类型输出目录的子项目配置;独立的 `tsconfig.test.json`、只含 vite.config 的 `tsconfig.node.json` 等无关上下文不参与判定)配置一段 `"paths": { "<remote>/*": ["<types目录>/<remote>.d/*"] }` 后,同形态导入即解析到转发模块获得**源码级类型**(props/函数签名精确,错误 props/参数编译失败)——应用上下文配置了 paths 的远程会自动跳过同名宽松声明避免遮蔽,启用说明见生成目录内 `_paths.d.ts`。
|
|
750
750
|
|
|
751
|
+
类型生成支持字符串或数组 `extends`(后项覆盖前项)、指向目录的 `references`,并按声明文件目录解析继承路径。`baseUrl` 与 `paths` 独立继承。多个实际应用上下文的远程 `paths` 接管不一致时,会保留默认宽松声明并给出中文提示;需要精确类型时请统一这些应用配置。生命周期错误 `MFU-012` 的 `cause` 保留 setup/onSession 抛出的原始异常。
|
|
752
|
+
|
|
751
753
|
### 9. `AppContext` — 跨应用传值与方法引用(`@fulgurjs/federation/runtime`)
|
|
752
754
|
|
|
753
755
|
宿主向子应用传值、子应用向宿主反向注册方法,一律走这条一等公民通道(对标乾坤 `props`,但带类型与错误契约)——不再各自挂 `window.*` 裸口子。
|
|
@@ -1108,7 +1110,7 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
1108
1110
|
|
|
1109
1111
|
- Vue 3 与 React 18–19 的**浏览器客户端**联邦为支持面;不支持 SSR / React Server Components / Next.js 全栈 / React Native / Node 服务端加载远程 / Vue 与 React 组件直接混渲染(同一页面同时用两套框架渲染组件树)。两框架各自纯项目互不引入对方;跨框架消费**纯 TS 模块**(如 Vue 宿主加载 React 远程的 utils)可用
|
|
1110
1112
|
- React 侧不承诺组件保活:`createReactHostPages` 不提供 `keepAliveNames`(Vue 的 KeepAlive 专属);页面表里的 `keepAlive` 字段在 React 侧只作普通扩展位。重复打开已下载页面的模块复用照常
|
|
1111
|
-
- 跨源 Fast Refresh
|
|
1113
|
+
- 跨源 Fast Refresh(5.2.0 修复):远程 React 组件修改(文本/样式/Hooks 结构不变的兼容改动)自动热更新到正在显示的宿主页面并保留组件本地状态,普通 TS 模块修改自动传播到引用它的组件边界——零手动刷新(插件保证全页单一 react-refresh 实例)。React Refresh 不兼容的导出/Hooks 结构变化、Vite 要求 full-reload 的改动按框架标准重新挂载/整页刷新;不承诺任意改动保活
|
|
1112
1114
|
- 不兼容 originjs 的 `virtual:__federation__` 旧写法
|
|
1113
1115
|
- 不支持 SSR(检测到即警告并禁用钩子)
|
|
1114
1116
|
- 无浏览器 DevTools 扩展(提供 `window.__FULGURJS_SCOPE__ / __FULGURJS_INFO__` 调试面)
|
|
@@ -1120,7 +1122,7 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
1120
1122
|
- [`docs/webpack-mf-对照与缺口.md`](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/webpack-mf-对照与缺口.md) — webpack MF 逐项对照与明确不支持清单
|
|
1121
1123
|
- [`docs/沙箱边界审计.md`](https://github.com/chenmingye/fulgurjs-federation/blob/master/docs/沙箱边界审计.md) — CSS / 全局变量 / 公共依赖三维度互扰实测
|
|
1122
1124
|
- [`DESIGN.md`](https://github.com/chenmingye/fulgurjs-federation/blob/master/DESIGN.md) — 架构设计、对齐总表、测试与验收方案
|
|
1123
|
-
- 可复制示例:[`examples/
|
|
1125
|
+
- 可复制示例:[`examples/vue/{host,remote}`](./examples) 与 [`examples/react/{host,remote}`](./examples)(四个完整工程,npm registry 精确正式包安装即跑,见 examples 总入口);仓库内 e2e 回归夹具见 `fixtures/`(link: 本地插件)
|
|
1124
1126
|
|
|
1125
1127
|
## 开发与测试
|
|
1126
1128
|
|
|
@@ -1144,7 +1146,7 @@ CI(GitHub Actions):
|
|
|
1144
1146
|
- `test`:单测 + 双口径 typecheck(pinned / latest)+ build 门禁(runtime gzip ≤ 9216B、错误码三方一致性);
|
|
1145
1147
|
- `e2e`:Vue + React 的 dev/fault × Vite 6.4.3 / 7.3.6 / 8.3.0 兼容矩阵;
|
|
1146
1148
|
- `prod-e2e`:隔离 NGINX 下的 Vue + React 生产套件;`tarball`:真实打包消费者检查;
|
|
1147
|
-
- `vite5`:schedule/workflow_dispatch
|
|
1149
|
+
- `vite5`:schedule/workflow_dispatch 运行最低支持线(Vite 5.1.4 全量 dev/fault/react 套件;5.2.0 起双 client 错误覆盖层缺陷已修复,无 skip 项)。
|
|
1148
1150
|
|
|
1149
1151
|
fixtures 测试与真实项目验收分别记录;fixture 全过不代表 MES 双环境已完成验收。
|
|
1150
1152
|
|
package/dist/context.cjs
CHANGED
|
@@ -32,8 +32,8 @@ module.exports = __toCommonJS(context_exports);
|
|
|
32
32
|
var FgError = class extends Error {
|
|
33
33
|
code;
|
|
34
34
|
details;
|
|
35
|
-
constructor(code, message, details) {
|
|
36
|
-
super(`[fulgurjs:${code}] ${message}
|
|
35
|
+
constructor(code, message, details, options) {
|
|
36
|
+
super(`[fulgurjs:${code}] ${message}`, options);
|
|
37
37
|
this.name = "FgError";
|
|
38
38
|
this.code = code;
|
|
39
39
|
this.details = details;
|
package/dist/context.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
var FgError = class extends Error {
|
|
3
3
|
code;
|
|
4
4
|
details;
|
|
5
|
-
constructor(code, message, details) {
|
|
6
|
-
super(`[fulgurjs:${code}] ${message}
|
|
5
|
+
constructor(code, message, details, options) {
|
|
6
|
+
super(`[fulgurjs:${code}] ${message}`, options);
|
|
7
7
|
this.name = "FgError";
|
|
8
8
|
this.code = code;
|
|
9
9
|
this.details = details;
|