@fulgurjs/federation 0.4.2 → 0.5.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 +20 -7
- package/DESIGN.md +8 -8
- package/README.md +49 -49
- package/dist/cli.js +43 -43
- package/dist/config.cjs +13 -13
- package/dist/config.d.cts +20 -20
- package/dist/config.d.ts +20 -20
- package/dist/config.js +11 -11
- package/dist/index.cjs +139 -139
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +139 -139
- package/dist/pages.cjs +9 -9
- package/dist/pages.d.cts +7 -7
- package/dist/pages.d.ts +7 -7
- package/dist/pages.js +7 -7
- package/dist/runtime.js +2 -2
- package/docs/manual.html +23 -23
- package/docs/webpack-mf-/345/257/271/347/205/247/344/270/216/347/274/272/345/217/243.md +1 -1
- package/docs//346/262/231/347/256/261/350/276/271/347/225/214/345/256/241/350/256/241.md +1 -1
- package/docs//350/277/201/347/247/273/346/214/207/345/215/227.md +8 -8
- package/examples/fulgur.config.example.ts +4 -4
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0(2026-09-19)
|
|
4
|
+
|
|
5
|
+
### 变更(品牌全面对齐,breaking)
|
|
6
|
+
|
|
7
|
+
- 全品牌从 `fulgur` 对齐为 **`fulgurjs`**(npm 上 fulgur 组织名被占用):
|
|
8
|
+
- CLI 命令:`fulgur` → **`fulgurjs`**(`npx fulgurjs init` / `npx fulgurjs doctor`)
|
|
9
|
+
- 虚拟模块:`virtual:fulgur-runtime` → **`virtual:fulgurjs-runtime`**(代理模块同步更名)
|
|
10
|
+
- 全局单例:`__FULGUR_RUNTIME__` → **`__FULGURJS_RUNTIME__`**(`__FULGURJS_APP_CONFIG__` / `__FULGURJS_SCOPE__` / `__FULGURJS_INFO__` 同步)
|
|
11
|
+
- 产物文件名:`fulgur-remoteEntry.js` / `fulgur-manifest.json` → **`fulgurjs-remoteEntry.js`** / **`fulgurjs-manifest.json`**(NGINX 规则同步更名)
|
|
12
|
+
- 配置文件:`fulgur.config.ts` → **`fulgurjs.config.ts`**;错误前缀 `[fulgur:*]` → `[fulgurjs:*]`;运行时事件 `fulgur:error` → `fulgurjs:error`
|
|
13
|
+
- GitHub 仓库:**fulgurjs-federation**(旧地址自动重定向)
|
|
14
|
+
- 升级方式:0.4.x 用户全局替换 `fulgur` → `fulgurjs`(导入/全局名/NGINX 文件名/CLI 命令)即可。
|
|
15
|
+
|
|
3
16
|
## 0.4.2(2026-09-19)
|
|
4
17
|
|
|
5
18
|
### 修复(npm 发布面)
|
|
@@ -13,7 +26,7 @@
|
|
|
13
26
|
|
|
14
27
|
### 变更(规则自动化)
|
|
15
28
|
|
|
16
|
-
- **任何文件都可以直接 `import { ... } from 'virtual:
|
|
29
|
+
- **任何文件都可以直接 `import { ... } from 'virtual:fulgurjs-runtime'`**(原 DEV-008 规则自动化):
|
|
17
30
|
exposes 目标文件(远程页面)里的静态导入,dev 下由插件自动改写为惰性单例委托模块
|
|
18
31
|
(求值期零副作用、调用期转发页面级运行时单例)。用户不再需要知道
|
|
19
32
|
「宿主/远程页面取运行时的不同姿势」,0.4.0 的手工 globalThis 写法已无需使用。
|
|
@@ -22,22 +35,22 @@
|
|
|
22
35
|
|
|
23
36
|
### 修复
|
|
24
37
|
|
|
25
|
-
- runtime 两个存量 TS 断言错误(as Error → as
|
|
38
|
+
- runtime 两个存量 TS 断言错误(as Error → as FulgurjsError)与 fallback 源码契约断言同步。
|
|
26
39
|
|
|
27
40
|
## 0.4.0(2026-09-18)
|
|
28
41
|
|
|
29
42
|
开箱即用批次(A→E)全部落地;W7 发布链按用户指示顺延(未发布 npm)。
|
|
30
43
|
|
|
31
44
|
### 新增
|
|
32
|
-
- **CLI(主包内置 bin `
|
|
33
|
-
- `
|
|
45
|
+
- **CLI(主包内置 bin `fulgurjs`)**
|
|
46
|
+
- `fulgurjs init`:起步模板(带注释的 `fulgurjs.config.ts`:宿主/远程/页面路由表/部署形态,
|
|
34
47
|
单文件可入库可复跑)+ 配置校验(CFG 三段式报错)+ 输出可直接粘贴的样板
|
|
35
48
|
(各应用 federation() vite 块、NGINX no-cache 站点模板、通用接入核对清单);
|
|
36
49
|
**项目无关**——不内置任何具体项目的模板、锚点或文件改写
|
|
37
|
-
- `
|
|
50
|
+
- `fulgurjs doctor`:部署面体检——remoteEntry/manifest/index.html 的 200/no-cache/JS 形态、
|
|
38
51
|
CORS、chunk 抽样可达(含 index.html 引用与一跳下钻、200-HTML 回退伪装识别)、
|
|
39
52
|
版本协商 skew 预演、`--dev` 模式端口/容器入口探测;`--json` 供 CI
|
|
40
|
-
- **W4 跨应用全局配置协商**:runtime 新增 `
|
|
53
|
+
- **W4 跨应用全局配置协商**:runtime 新增 `provideFulgurjsAppConfig` / `getFulgurjsAppConfig`
|
|
41
54
|
(页面级单例、浅合并、globalThis 镜像)——EP locale/size 类跨副本配置的机制化收编
|
|
42
55
|
- **W5 诊断补码**:CFG-007(remotes 对象形式误用 name@ 前缀)、CFG-008(shared 非法组合)、
|
|
43
56
|
DEV-010(dev 冷启动预构建窗口提示);BLD-003 必填 props 扫描器(按实测降级为手册核对项)
|
|
@@ -51,6 +64,6 @@
|
|
|
51
64
|
|
|
52
65
|
### 变更
|
|
53
66
|
- **插件去项目化(2026-09-19 定调)**:移除 init 中曾内置的具体项目集成模板/锚点/补丁
|
|
54
|
-
(历史实现见 git 历史);`
|
|
67
|
+
(历史实现见 git 历史);`fulgurjs init` 重写为纯通用脚手架,配置 schema 同步精简。
|
|
55
68
|
插件为所有项目服务,不做任何单一项目的形状。
|
|
56
69
|
- runtime gzip 5212 B(红线 ≤5250 内);单测 148/148;错误码 30 个全量文档对齐
|
package/DESIGN.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @fulgurjs/federation 设计方案 v0.2(全量对齐 Webpack MF 版)
|
|
2
2
|
|
|
3
|
-
> **品牌**:
|
|
3
|
+
> **品牌**:fulgurjs,拉丁语「闪电 · 辉光」,取自作者名中「烨」字的意译。
|
|
4
4
|
> 系列规划:`@fulgurjs/federation`(模块联邦)→ `@fulgurjs/micro`、`@fulgurjs/dts` …
|
|
5
|
-
> 内外命名统一 `
|
|
5
|
+
> 内外命名统一 `fulgurjs`(`virtual:fulgurjs-*` 虚拟模块、`window.__FULGURJS_*` 调试出口、`FulgurjsError` / MFU 错误码)。
|
|
6
6
|
|
|
7
7
|
> 状态:已实现并验证(2026-09-13)。测试结果:单测 76/76、fixtures dev e2e 10/10、容错/HMR-L3 2/2、fixtures prod e2e 8/8(隔离 NGINX 8999)、testbed dev 实测全通、testbed prod(本地 NGINX 测试站点)最小宿主消费真实远程产物实测通过;runtime gzip 4.4KB。已知问题见手册 §7。
|
|
8
8
|
> 日期:2026-09-12
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
### 2A. 核心配置(webpack 官方文档全部选项)
|
|
32
32
|
|
|
33
|
-
| # | webpack 选项 |
|
|
33
|
+
| # | webpack 选项 | fulgurjs | 实现方式与语义说明 |
|
|
34
34
|
|---|---|---|---|
|
|
35
35
|
| 1 | `name` | ✅ | 容器名;同时作为 uniqueName 决胜来源。重名冲突构建期检测并警告(对齐 webpack 对 `output.uniqueName` 的要求) |
|
|
36
36
|
| 2 | `filename` | ✅ | remoteEntry 文件名,稳定命名,利于 CDN 长缓存 |
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
### 2B. 运行时行为语义("效果一模一样"的实体,逐条 e2e 验收)
|
|
52
52
|
|
|
53
|
-
| # | webpack 行为 |
|
|
53
|
+
| # | webpack 行为 | fulgurjs 验收语义 |
|
|
54
54
|
|---|---|---|
|
|
55
55
|
| 1 | 版本协商:消费方拿到 scope 中**满足其 requiredVersion 的最高版本** | e2e 断言双版本场景加载的是高版本 |
|
|
56
56
|
| 2 | 多版本共存(非 singleton、不同 requiredVersion 可并存) | e2e 断言两版本模块图并存且各自正常 |
|
|
@@ -69,11 +69,11 @@
|
|
|
69
69
|
| 15 | 静态 remote 自动加载;加载失败 → 等价 `ScriptExternalLoadError` 的统一错误码(MFU-0xx 体系) | e2e:kill remote 断言错误码 + UI 错误边界 |
|
|
70
70
|
| 16 | `import('app1/Button')` 语法 + default/named unwrap 语义 | 所有用例的基础断言 |
|
|
71
71
|
| 17 | exposed 模块的样式自动随模块注入(dev / prod 都生效) | e2e:远程组件样式生效断言 |
|
|
72
|
-
| 18 | 异步边界:
|
|
72
|
+
| 18 | 异步边界:fulgurjs **自动注入**(等效 `automaticAsyncBoundary: true` 默认开启),用户不需要 webpack 的 bootstrap.js 手工模式;提供开关可关 | e2e:不写 bootstrap 直接跑通 |
|
|
73
73
|
|
|
74
74
|
### 2C. MF 2.0 / @module-federation/enhanced 配置
|
|
75
75
|
|
|
76
|
-
| # | 选项 |
|
|
76
|
+
| # | 选项 | fulgurjs | 说明 |
|
|
77
77
|
|---|---|---|---|
|
|
78
78
|
| 1 | `manifest` | ✅ | `mf-manifest.json`(资源清单 + 版本 + 公共路径),部署回滚 = 切 manifest 指针 |
|
|
79
79
|
| 2 | `runtimePlugins` | ✅ | runtime 钩子 API(init / get / loadShare 前后钩子) |
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
|
|
85
85
|
## 3. 比 webpack 更进一步的点
|
|
86
86
|
|
|
87
|
-
1. **自动异步边界**——webpack 要求手工 `import('./bootstrap')`,
|
|
87
|
+
1. **自动异步边界**——webpack 要求手工 `import('./bootstrap')`,fulgurjs 自动注入,配置零改动
|
|
88
88
|
2. **类型直连**——dev 下 remote 的补全与跳转是真源码级(webpack 需要额外 dts 工具链折腾)
|
|
89
89
|
3. **runtime 内核 gzip < 5KB**(CI 硬指标,对比 @module-federation/runtime 的 40KB+)
|
|
90
90
|
4. **一套配置 dev/prod 自动切换**——webpack 的 dev/prod 配置经常分裂两份
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
|
|
93
93
|
## 4. HMR 对齐承诺(dev 体验)
|
|
94
94
|
|
|
95
|
-
webpack 里 remote 模块 HMR 天然可用(同一构建系统)。
|
|
95
|
+
webpack 里 remote 模块 HMR 天然可用(同一构建系统)。fulgurjs 通过 host↔remote 双 dev-server HMR 桥对齐,分三档自动化验收:
|
|
96
96
|
|
|
97
97
|
- L1 组件热替换成功(页面不整页刷新)
|
|
98
98
|
- L2 状态保留(组件热替换后 local state 不丢,对齐 vue HMR 行为)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @fulgurjs/federation
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **fulgurjs** — 拉丁语「闪电 · 辉光」。
|
|
4
4
|
> 一个把 Vite 模块联邦做到开箱即用的插件:**一套配置,dev / prod 双引擎,语义对齐 Webpack Module Federation**。
|
|
5
5
|
|
|
6
6
|
  
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
- **exposes / remotes / shared 全语义**:`name@url` 语法、键重命名、promise-based remote、semver 全语法 requiredVersion、版本协商(最高版本胜出)、singleton / strictVersion、已加载版本永不替换、多版本共存、shareKey 重定向、多 shareScope
|
|
27
27
|
- **UMD / CJS-only 依赖开箱即用**:element-plus、avue 等只有 UMD/CJS 产物的依赖直接进 `optimizeDeps.include` 即可——dev 期插件自动把预构建产物内的 shared 键改道协商门面;build 期自动把 CJS `require(<shared>)` 重定向到垫片,双运行时免疫
|
|
28
28
|
- **自动异步边界**:top-level await 自动注入(es2022+),无需 webpack 式手工 `import('./bootstrap')`
|
|
29
|
-
- **稳定产物**:remoteEntry 固定文件名利于 CDN 长缓存;`
|
|
29
|
+
- **稳定产物**:remoteEntry 固定文件名利于 CDN 长缓存;`fulgurjs-manifest.json` 资源清单;expose 独立 chunk
|
|
30
30
|
- **容错(对齐 webpack MF 2.0 errorLoadRemote)**:加载重试 / 熔断 / 超时内置;`loadRemote(spec, { retries, fallbackModule })` 单次调用级覆盖——失败时返回 fallback 模块,错误事件仍显式发出(**绝不静默兜底**,不传则照旧抛错)
|
|
31
31
|
- **增强能力**:dts 类型直连(dev 补全直达 remote 源码)、`preloadRemote()` manifest 驱动精确预载、runtimePlugins 钩子
|
|
32
32
|
- **HMR 全链路**:remote 改动 → host 页面热更,L1 组件热替换 / L2 状态保留 / L3 错误覆盖与恢复
|
|
33
33
|
- **零报错纪律**:配置问题启动瞬间三段式报错;联邦失败显式抛错(错误码 + 可执行修复建议),**无任何静默兜底路径**
|
|
34
|
-
- **CLI(主包内置 bin)**:`
|
|
35
|
-
- **跨应用全局配置协商(W4)**:`
|
|
34
|
+
- **CLI(主包内置 bin)**:`fulgurjs init`——`fulgurjs.config.ts` 单配置驱动的迁移生成器(模板 = 真实工程验证形态:vite 配置/路由表/桥/联邦启动器/NGINX conf 全量编码,锚点补丁幂等可续跑);`fulgurjs doctor`——部署面体检(remoteEntry/manifest/HTML 缓存头与形态、CORS、chunk 抽样可达、版本 skew 预演、`--dev` 端口探测)
|
|
35
|
+
- **跨应用全局配置协商(W4)**:`provideFulgurjsAppConfig({ locale, size, ... })` 一次写入运行时页面级单例,各远程副本经 `getFulgurjsAppConfig()` 消费注入(EP locale/size 类问题的机制化收编)
|
|
36
36
|
- **全链路错误码体系(30 码)**:CFG/DEV/BLD/MFU 四段 + 手册 §8 码表防漂移校验
|
|
37
37
|
|
|
38
38
|
## 安装
|
|
@@ -97,7 +97,7 @@ export default defineConfig({
|
|
|
97
97
|
import Button from 'remote-a/Button'
|
|
98
98
|
|
|
99
99
|
// 动态导入 / 运行时 API
|
|
100
|
-
import { loadRemote, registerRemote, preloadRemote } from 'virtual:
|
|
100
|
+
import { loadRemote, registerRemote, preloadRemote } from 'virtual:fulgurjs-runtime'
|
|
101
101
|
|
|
102
102
|
const Chart = defineAsyncComponent(() => loadRemote('remote-a/Chart').then(m => m.default))
|
|
103
103
|
|
|
@@ -114,26 +114,26 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
> **在任何文件都可以直接这样导入**——包括 exposes 目标文件(远程页面)。插件会自动把远程页面里的
|
|
117
|
-
> 该导入改写为惰性单例委托(0.4.1 起,原 0.4.0 要求手工改用 `globalThis.
|
|
117
|
+
> 该导入改写为惰性单例委托(0.4.1 起,原 0.4.0 要求手工改用 `globalThis.__FULGURJS_RUNTIME__` 的规则已废除),
|
|
118
118
|
> 求值期零副作用、调用期自动转发页面级运行时单例,无需关心宿主/远程的区别。
|
|
119
119
|
|
|
120
120
|
> 以上只是最小面。**全部选项(remotes 四形态/shared 九个开关/dts/runtimePlugins…)、运行时 API、CLI、错误码见下方 [API 参考](#api-参考)。**
|
|
121
121
|
|
|
122
|
-
**没有别的步骤了。** dev 下 remote 跑它自己的 `vite dev`(容器入口 `/@
|
|
122
|
+
**没有别的步骤了。** dev 下 remote 跑它自己的 `vite dev`(容器入口 `/@fulgurjs-entry.js` 由插件中间件直出);build 下 expose 自动拆独立 chunk、shared 自动剥离——同一份配置两端通用。
|
|
123
123
|
|
|
124
124
|
## CLI:init 起步模板 + doctor 部署体检
|
|
125
125
|
|
|
126
126
|
```bash
|
|
127
|
-
# 1) 生成带注释的
|
|
128
|
-
npx
|
|
129
|
-
# 样例:examples/
|
|
127
|
+
# 1) 生成带注释的 fulgurjs.config.ts 起步模板(宿主/远程/页面路由表/部署形态,单文件可入库)
|
|
128
|
+
npx fulgurjs init # 已存在则拒绝,--force 覆盖
|
|
129
|
+
# 样例:examples/fulgurjs.config.example.ts(通用字段示例)
|
|
130
130
|
|
|
131
131
|
# 2) 校验配置并输出可直接粘贴的样板:各应用 federation() 块、NGINX no-cache 站点模板、接入核对清单
|
|
132
|
-
npx
|
|
132
|
+
npx fulgurjs init --config fulgurjs.config.ts
|
|
133
133
|
|
|
134
134
|
# 3) 部署体检(CI 可嵌):缓存头/资源形态/CORS/chunk 可达/版本 skew
|
|
135
|
-
npx
|
|
136
|
-
npx
|
|
135
|
+
npx fulgurjs doctor --base http://your-site --apps app-a,app-b
|
|
136
|
+
npx fulgurjs doctor --base http://localhost:5173 --apps app-a --dev
|
|
137
137
|
```
|
|
138
138
|
|
|
139
139
|
**插件保持项目无关**:init 不改写任何项目文件,不内置任何具体项目的模板或补丁;权限路由、
|
|
@@ -154,7 +154,7 @@ import { federation } from '@fulgurjs/federation'
|
|
|
154
154
|
| 选项 | 类型 | 默认 | 说明 |
|
|
155
155
|
|---|---|---|---|
|
|
156
156
|
| `name` | `string` **必填** | — | 容器名。同页面宿主/远程必须唯一(也是 uniqueName);须匹配 `/^[a-zA-Z][\w.-]*$/` |
|
|
157
|
-
| `filename` | `string` | `'
|
|
157
|
+
| `filename` | `string` | `'fulgurjs-remoteEntry.js'` | prod 容器入口文件名(固定文件名,CDN 可长缓存) |
|
|
158
158
|
| `exposes` | `Record<string, string \| { import: string; name?: string }>` | — | 对外暴露模块:键 `'./X'`,值源文件路径;`name` 为稳定 chunk 文件名 |
|
|
159
159
|
| `remotes` | `Record<string, string \| RemoteConfig \| (() => Promise<any>)>` | — | 消费的远程,三种形态见下表 |
|
|
160
160
|
| `shared` | `string[] \| Record<string, string \| SharedHint>` | — | 共享依赖;字符串简写 = requiredVersion(缺省从本应用 package.json 推断) |
|
|
@@ -163,7 +163,7 @@ import { federation } from '@fulgurjs/federation'
|
|
|
163
163
|
| `library` | `{ type?: string }` | — | 仅接受 esm/module(webpack 宿主 interop 尚未支持,告警) |
|
|
164
164
|
| `runtime` | `string \| false` | 内置运行时 | 自定义运行时模块路径;`false` 禁用内置运行时 |
|
|
165
165
|
| `runtimeChunk` | `boolean \| 'single'` | — | 运行时是否拆独立 chunk |
|
|
166
|
-
| `manifest` | `boolean` | `true` | prod 构建生成 `
|
|
166
|
+
| `manifest` | `boolean` | `true` | prod 构建生成 `fulgurjs-manifest.json`(preloadRemote 依赖它) |
|
|
167
167
|
| `runtimePlugins` | `string[]` | `[]` | 运行时插件模块路径列表(写法见「运行时插件」) |
|
|
168
168
|
| `dts` | `boolean \| { dir?: string }` | `true` | dev 下拉取远程 manifest 生成类型声明——宿主写 `import X from 'remote-a/X'` 补全直达远程源码 |
|
|
169
169
|
| `devSharedSelf` | `boolean` | 纯远程 `true`;有 `remotes` 的宿主 `false` | dev 下自身源码(含依赖)是否参与 shared 协商改写。**双向联邦**(既 expose 又消费 remote)的宿主/远程需显式 `true`,否则 prod 双 vue 实例 |
|
|
@@ -175,7 +175,7 @@ import { federation } from '@fulgurjs/federation'
|
|
|
175
175
|
|
|
176
176
|
```ts
|
|
177
177
|
remotes: {
|
|
178
|
-
// ① 字符串单地址:dev 自动拼 /@
|
|
178
|
+
// ① 字符串单地址:dev 自动拼 /@fulgurjs-entry.js,prod 自动拼 filename
|
|
179
179
|
'remote-a': 'http://localhost:5101',
|
|
180
180
|
// ② '自报名@url':重命名语义(仅字符串形式支持;对象形式不支持 name@,配置期即报 CFG-007)
|
|
181
181
|
'checkout': 'shop@http://localhost:5102',
|
|
@@ -217,16 +217,16 @@ shared: {
|
|
|
217
217
|
|
|
218
218
|
版本裁决语义对齐 webpack:满足 requiredVersion 的最高版本胜出;已加载版本永不替换;singleton 收敛到唯一实例(skew 告警 MFU-010);strictVersion 不满足抛 MFU-003。
|
|
219
219
|
|
|
220
|
-
### 2. 运行时 API — `virtual:
|
|
220
|
+
### 2. 运行时 API — `virtual:fulgurjs-runtime`
|
|
221
221
|
|
|
222
222
|
**任何文件都直接静态导入**——宿主页面、exposes 目标文件(远程页面)都一样,插件自动保证同一页面只有一个运行时实例(远程页面里的导入会被自动改写为惰性单例委托,0.4.1 起):
|
|
223
223
|
|
|
224
224
|
```ts
|
|
225
225
|
// 宿主页面、远程页面,写法完全一致
|
|
226
|
-
import { loadRemote,
|
|
226
|
+
import { loadRemote, provideFulgurjsAppConfig } from 'virtual:fulgurjs-runtime'
|
|
227
227
|
```
|
|
228
228
|
|
|
229
|
-
> 仍可绕过代理直取全局单例(等价,调试用):`(globalThis as any).
|
|
229
|
+
> 仍可绕过代理直取全局单例(等价,调试用):`(globalThis as any).__FULGURJS_RUNTIME__`。
|
|
230
230
|
|
|
231
231
|
#### 函数总表
|
|
232
232
|
|
|
@@ -240,9 +240,9 @@ import { loadRemote, provideFulgurAppConfig } from 'virtual:fulgur-runtime'
|
|
|
240
240
|
| `registerShare` | `(scope, name, version, get, opts?) => void` | 手工注册共享模块(一般由 init 模块自动完成) |
|
|
241
241
|
| `initSharing` | `(scopeName?) => ShareScopeMap` | 初始化共享作用域(一般由 init 模块自动完成) |
|
|
242
242
|
| `registerPlugins` | `(plugins: RuntimePlugin[]) => void` | 注册运行时插件(见下) |
|
|
243
|
-
| `
|
|
244
|
-
| `
|
|
245
|
-
| `getRuntime` | `() =>
|
|
243
|
+
| `provideFulgurjsAppConfig` | `(config: Record<string, any>) => void` | **跨应用全局配置写入**(宿主桥一次写入;浅合并;镜像到 `globalThis.__FULGURJS_APP_CONFIG__`) |
|
|
244
|
+
| `getFulgurjsAppConfig` | `() => Record<string, any>` | 读取全局配置(远程 federatedBoot 消费注入 locale/size 等) |
|
|
245
|
+
| `getRuntime` | `() => FulgurjsRuntime` | 取运行时单例本体(与 `__FULGURJS_RUNTIME__` 同一实例) |
|
|
246
246
|
| `version` | `string` | 运行时/插件版本(跨源副本一致性诊断用) |
|
|
247
247
|
| `unwrapDefault` | `(ns: any) => any` | ESM/CJS default interop 工具 |
|
|
248
248
|
|
|
@@ -257,10 +257,10 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
257
257
|
})
|
|
258
258
|
```
|
|
259
259
|
|
|
260
|
-
#### 运行时插件(`runtimePlugins: ['./src/
|
|
260
|
+
#### 运行时插件(`runtimePlugins: ['./src/fulgurjsPlugin.ts']`)
|
|
261
261
|
|
|
262
262
|
```ts
|
|
263
|
-
import type { RuntimePlugin } from 'virtual:
|
|
263
|
+
import type { RuntimePlugin } from 'virtual:fulgurjs-runtime'
|
|
264
264
|
|
|
265
265
|
export default {
|
|
266
266
|
name: 'my-plugin',
|
|
@@ -279,20 +279,20 @@ export default {
|
|
|
279
279
|
|
|
280
280
|
| 出口 | 内容 |
|
|
281
281
|
|---|---|
|
|
282
|
-
| `window.
|
|
283
|
-
| `window.
|
|
284
|
-
| `window.
|
|
285
|
-
| `window` 事件 `
|
|
282
|
+
| `window.__FULGURJS_SCOPE__` | share scope 实时协商结果(键 → 版本 → `{ get, from, loaded }`) |
|
|
283
|
+
| `window.__FULGURJS_INFO__` | `{ remotes: { [名]: { entry, status, lastLoadMs, error } }, errors: [] }` |
|
|
284
|
+
| `window.__FULGURJS_APP_CONFIG__` | W4 全局配置镜像 |
|
|
285
|
+
| `window` 事件 `fulgurjs:error` | `CustomEvent<{ remote, error }>`,所有远程加载/共享错误都会发出 |
|
|
286
286
|
|
|
287
|
-
### 3. `
|
|
287
|
+
### 3. `defineFulgurjsPages` — 宿主页面路由表(`@fulgurjs/federation/pages`)
|
|
288
288
|
|
|
289
289
|
宿主把「URL 路径 → 远程 exposes 键」的映射表交给它校验,带参路由的静默冲突在启动期报错而不是运行时加载错组件:
|
|
290
290
|
|
|
291
291
|
```ts
|
|
292
|
-
import {
|
|
293
|
-
import remoteSchema from 'virtual:
|
|
292
|
+
import { defineFulgurjsPages } from '@fulgurjs/federation/pages'
|
|
293
|
+
import remoteSchema from 'virtual:fulgurjs-remote-schema' // dev 自动生成;build 恒为空(诚实降级)
|
|
294
294
|
|
|
295
|
-
export const PAGES =
|
|
295
|
+
export const PAGES = defineFulgurjsPages(
|
|
296
296
|
[
|
|
297
297
|
{ route: '/remote-a/home', name: 'RemoteAHome', title: '首页' },
|
|
298
298
|
// 带参路由:缺省推导 spec = 去首段 + 剥 :参 段;与其它条目冲突时 ERROR,
|
|
@@ -318,14 +318,14 @@ export const PAGES = defineFulgurPages(
|
|
|
318
318
|
| R4 | ERROR | 静态路由被更靠前的带参路由遮蔽(先到先得)/路由完全重复 |
|
|
319
319
|
| R5 | WARN | name 重复(vue-router 命名跳转歧义) |
|
|
320
320
|
|
|
321
|
-
`
|
|
321
|
+
`validateFulgurjsPages(pages, options)` 为独立导出:返回违例清单不抛错,便于自测。
|
|
322
322
|
|
|
323
|
-
### 4. `
|
|
323
|
+
### 4. `fulgurjs.config.ts` — CLI 单配置文件(`@fulgurjs/federation/config`)
|
|
324
324
|
|
|
325
325
|
```ts
|
|
326
|
-
import {
|
|
326
|
+
import { defineFulgurjsConfig } from '@fulgurjs/federation/config'
|
|
327
327
|
|
|
328
|
-
export default
|
|
328
|
+
export default defineFulgurjsConfig({
|
|
329
329
|
root: process.cwd(), // 工程根(monorepo 根或单应用仓库根)
|
|
330
330
|
apps: [
|
|
331
331
|
{
|
|
@@ -354,9 +354,9 @@ export default defineFulgurConfig({
|
|
|
354
354
|
|
|
355
355
|
| 命令 | 说明 |
|
|
356
356
|
|---|---|
|
|
357
|
-
| `
|
|
358
|
-
| `
|
|
359
|
-
| `
|
|
357
|
+
| `fulgurjs init` | 在当前目录生成带注释的 `fulgurjs.config.ts` 起步模板;`--template <path>` 指定输出路径;已存在拒绝覆盖,`--force` 强制 |
|
|
358
|
+
| `fulgurjs init --config <path>` | 校验配置(CFG 三段式报错)+ 输出各应用 `federation()` 粘贴块、NGINX no-cache 站点模板、8 条通用核对清单 |
|
|
359
|
+
| `fulgurjs doctor --base <URL> --apps <a,b,c>` | 部署体检:remoteEntry/manifest/index.html 的 200/no-cache/JS 形态、CORS、chunk 抽样可达、版本 skew 预演。`--dev` 检查 dev 容器入口;`--json` 输出 JSON(CI 断言);`--chunk-sample N` 控制抽样数(默认 16)。**退出码:有 FAIL 即 1**,可直接做 CI 门禁 |
|
|
360
360
|
|
|
361
361
|
### 6. 错误码总表(30 个)
|
|
362
362
|
|
|
@@ -376,7 +376,7 @@ export default defineFulgurConfig({
|
|
|
376
376
|
| | `DEV-004` | 已知 UMD-only 依赖不在 optimizeDeps.include(预构建内联本地 vue 风险) |
|
|
377
377
|
| | `DEV-005` | remotes dev URL 端口无监听 |
|
|
378
378
|
| | `DEV-006` | 宿主/远程插件版本不一致 |
|
|
379
|
-
| | `DEV-008` | 远程页面静态导入 virtual:
|
|
379
|
+
| | `DEV-008` | 远程页面静态导入 virtual:fulgurjs-runtime(破坏渲染上下文) |
|
|
380
380
|
| | `DEV-009` | 门面/虚拟模块 404(.vite 缓存漂移,需清缓存重启) |
|
|
381
381
|
| | `DEV-010` | dev 冷启动预构建窗口提示(首轮 30~60s 瞬态,非故障) |
|
|
382
382
|
| BLD 构建期 | `BLD-001` | expose 源文件解析失败 |
|
|
@@ -393,18 +393,18 @@ export default defineFulgurConfig({
|
|
|
393
393
|
| | `MFU-009` | 加载到的模块没有任何导出 |
|
|
394
394
|
| | `MFU-010` | singleton 共享版本漂移(使用作用域版本,告警) |
|
|
395
395
|
|
|
396
|
-
每个码的完整排查文案见 [`docs/manual.html`](./docs/manual.html) §8;`
|
|
396
|
+
每个码的完整排查文案见 [`docs/manual.html`](./docs/manual.html) §8;`fulgurjs doctor` 可提前把部署面的 MFU-001 类问题拦在上线前。
|
|
397
397
|
|
|
398
398
|
### 7. 产物与端点约定
|
|
399
399
|
|
|
400
400
|
| 环境 | 路径 | 说明 |
|
|
401
401
|
|---|---|---|
|
|
402
|
-
| dev | `/<base>/@
|
|
403
|
-
| dev | `/<base>/@
|
|
404
|
-
| prod | `/<base>/
|
|
405
|
-
| prod | `/<base>/
|
|
402
|
+
| dev | `/<base>/@fulgurjs-entry.js` | 远程容器入口(插件中间件直出,自包含) |
|
|
403
|
+
| dev | `/<base>/@fulgurjs-manifest.json` | dev manifest(宿主 dts / preloadRemote 消费) |
|
|
404
|
+
| prod | `/<base>/fulgurjs-remoteEntry.js` | 固定文件名容器入口(内容每次构建变——**必须 no-cache**) |
|
|
405
|
+
| prod | `/<base>/fulgurjs-manifest.json` | expose chunk/CSS 清单(preloadRemote 消费,**no-cache**) |
|
|
406
406
|
|
|
407
|
-
NGINX 部署模板(no-cache 规则 + 深链回退)用 `
|
|
407
|
+
NGINX 部署模板(no-cache 规则 + 深链回退)用 `fulgurjs init --config` 自动生成,样例见 [`docs/manual.html`](./docs/manual.html)。
|
|
408
408
|
|
|
409
409
|
## ⚠️ 首次使用避坑指南(真实迁移项目踩坑实录)
|
|
410
410
|
|
|
@@ -467,7 +467,7 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
467
467
|
所有配置问题在 `vite` 启动瞬间即报,固定三段式,可直接照抄修正:
|
|
468
468
|
|
|
469
469
|
```
|
|
470
|
-
[
|
|
470
|
+
[fulgurjs] Invalid federation() config — remotes["remote-a"] has no address (need one of external / dev / prod)
|
|
471
471
|
got: {"dev":""}
|
|
472
472
|
expected: at least one address; with only one URL it is used for both dev and prod
|
|
473
473
|
example: remotes: { 'remote-a': 'http://localhost:5101' }
|
|
@@ -478,13 +478,13 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
478
478
|
|
|
479
479
|
统一错误码体系(CFG/DEV/BLD/MFU 四段共 30 个)——**完整总表见上方 [API 参考 §6](#6-错误码总表30-个)**;报错文案一律「现象 → 根因 → 修法」三段式。
|
|
480
480
|
|
|
481
|
-
调试出口:`window.
|
|
481
|
+
调试出口:`window.__FULGURJS_SCOPE__`(share 协商实时结果)、`window.__FULGURJS_INFO__`(remote 状态/耗时/错误)。
|
|
482
482
|
|
|
483
483
|
## 边界(明确不支持)
|
|
484
484
|
|
|
485
485
|
- 仅 Vue 3 生态(React 适配不在当前范围);不兼容 originjs 的 `virtual:__federation__` 旧写法
|
|
486
486
|
- 不支持 SSR(检测到即警告并禁用钩子)
|
|
487
|
-
- 无浏览器 DevTools 扩展(提供 `window.
|
|
487
|
+
- 无浏览器 DevTools 扩展(提供 `window.__FULGURJS_SCOPE__ / __FULGURJS_INFO__` 调试面)
|
|
488
488
|
- 无 JS 沙箱 / CSS 隔离——联邦是同 realm 共存架构,靠 shared 单例协商防止双运行时(详见 `docs/沙箱边界审计.md` 的三维度实测)
|
|
489
489
|
|
|
490
490
|
## 文档
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/config.ts
|
|
13
|
-
async function
|
|
13
|
+
async function loadFulgurjsConfig(configPath) {
|
|
14
14
|
const { pathToFileURL, fileURLToPath } = await import("node:url");
|
|
15
15
|
const { createRequire } = await import("node:module");
|
|
16
16
|
const fs2 = await import("node:fs");
|
|
@@ -18,8 +18,8 @@ async function loadFulgurConfig(configPath) {
|
|
|
18
18
|
const path2 = await import("node:path");
|
|
19
19
|
const selfDir = path2.dirname(fileURLToPath(import.meta.url));
|
|
20
20
|
const selfConfigJs = path2.join(selfDir, "config.js");
|
|
21
|
-
const SELF_SPEC = fs2.existsSync(selfConfigJs) ? pathToFileURL(selfConfigJs).href : "@
|
|
22
|
-
const rewriteSelfImports = (source) => source.replace(/(['"])@
|
|
21
|
+
const SELF_SPEC = fs2.existsSync(selfConfigJs) ? pathToFileURL(selfConfigJs).href : "@fulgurjs-federation-config-unavailable";
|
|
22
|
+
const rewriteSelfImports = (source) => source.replace(/(['"])@fulgurjs\/federation\/config\1/g, (_m, q) => `${q}${SELF_SPEC}${q}`);
|
|
23
23
|
const importConfigs = async (cacheKey) => {
|
|
24
24
|
return await import(`${cacheKey}?t=${Date.now()}`);
|
|
25
25
|
};
|
|
@@ -28,7 +28,7 @@ async function loadFulgurConfig(configPath) {
|
|
|
28
28
|
mod = { default: JSON.parse(fs2.readFileSync(configPath, "utf8")) };
|
|
29
29
|
} else {
|
|
30
30
|
const source = rewriteSelfImports(fs2.readFileSync(configPath, "utf8"));
|
|
31
|
-
const tmpBase = path2.join(os.tmpdir(), `
|
|
31
|
+
const tmpBase = path2.join(os.tmpdir(), `fulgurjs-config-${Date.now()}`);
|
|
32
32
|
if (/\.(ts|mts|cts)$/.test(configPath)) {
|
|
33
33
|
try {
|
|
34
34
|
const tmpTs = `${tmpBase}.ts`;
|
|
@@ -60,18 +60,18 @@ async function loadFulgurConfig(configPath) {
|
|
|
60
60
|
const cfg = mod.default;
|
|
61
61
|
if (!cfg?.root) {
|
|
62
62
|
throw new Error(
|
|
63
|
-
`[
|
|
63
|
+
`[fulgurjs:init] \u914D\u7F6E\u7F3A\u5C11 root\uFF08\u5DE5\u7A0B\u6839\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84\uFF09
|
|
64
64
|
\u6839\u56E0\uFF1ACLI \u9700\u8981\u77E5\u9053\u5728\u54EA\u4E2A\u5DE5\u7A0B\u4E0A\u505A\u96C6\u6210
|
|
65
|
-
\u4FEE\u6CD5\
|
|
65
|
+
\u4FEE\u6CD5\uFF1Afulgurjs.config.ts \u9876\u5C42\u8865 root: '/abs/path/to/repo'\uFF08\u8D77\u6B65\u6A21\u677F\uFF1Afulgurjs init\uFF09`
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
if (!Array.isArray(cfg.apps) || cfg.apps.length === 0) {
|
|
69
|
-
throw new Error("[
|
|
69
|
+
throw new Error("[fulgurjs:init] \u914D\u7F6E\u7F3A\u5C11 apps\uFF08\u81F3\u5C11\u4E00\u4E2A\u5BBF\u4E3B\u6216\u8FDC\u7A0B\u5E94\u7528\uFF09");
|
|
70
70
|
}
|
|
71
71
|
for (const app of cfg.apps) {
|
|
72
72
|
if (!app.host && !app.remote) {
|
|
73
73
|
throw new Error(
|
|
74
|
-
`[
|
|
74
|
+
`[fulgurjs:init] \u5E94\u7528 "${app.path}" \u65E2\u65E0 host \u4E5F\u65E0 remote \u89D2\u8272
|
|
75
75
|
\u6839\u56E0\uFF1A\u5E94\u7528\u5FC5\u987B\u81F3\u5C11\u58F0\u660E\u4E00\u4E2A\u89D2\u8272
|
|
76
76
|
\u4FEE\u6CD5\uFF1A\u5BBF\u4E3B\u8865 host: { pages, remotePrefixes, remotes }\uFF0C\u8FDC\u7A0B\u8865 remote: { exposes }`
|
|
77
77
|
);
|
|
@@ -142,11 +142,11 @@ function nginxSnippetFor(cfg) {
|
|
|
142
142
|
return ` location ${b} {
|
|
143
143
|
try_files $uri $uri/ ${hostIndex};
|
|
144
144
|
|
|
145
|
-
location = ${b}/
|
|
145
|
+
location = ${b}/fulgurjs-remoteEntry.js {
|
|
146
146
|
add_header Cache-Control "no-cache";
|
|
147
147
|
add_header Access-Control-Allow-Origin "*";
|
|
148
148
|
}
|
|
149
|
-
location = ${b}/
|
|
149
|
+
location = ${b}/fulgurjs-manifest.json {
|
|
150
150
|
add_header Cache-Control "no-cache";
|
|
151
151
|
add_header Access-Control-Allow-Origin "*";
|
|
152
152
|
}
|
|
@@ -187,7 +187,7 @@ function appSummary(app) {
|
|
|
187
187
|
return lines.join("\n");
|
|
188
188
|
}
|
|
189
189
|
async function inspectConfig(configPath) {
|
|
190
|
-
const cfg = await
|
|
190
|
+
const cfg = await loadFulgurjsConfig(configPath);
|
|
191
191
|
const out = [];
|
|
192
192
|
out.push(`${MARK} \u914D\u7F6E\u6821\u9A8C\u901A\u8FC7\uFF1Aroot=${cfg.root}\uFF0Capps=${cfg.apps.length}`);
|
|
193
193
|
out.push("\u5E94\u7528\u6458\u8981\uFF1A");
|
|
@@ -205,10 +205,10 @@ async function inspectConfig(configPath) {
|
|
|
205
205
|
out.push("2. expose \u4E00\u5F8B\u6307\u5411\u72EC\u7ACB\u9875\uFF08\u9875\u9762\u4ECE\u8DEF\u7531\u53D6\u53C2\uFF09\uFF1B\u7EC4\u4EF6\u9700\u8981\u5FC5\u586B props \u65F6\u7ED9\u9ED8\u8BA4\u503C\uFF08BLD-003\uFF09");
|
|
206
206
|
out.push("3. shared \u91CC vue / vue-router / pinia \u5EFA\u8BAE singleton: true\u2014\u2014\u8DE8\u5E94\u7528\u5FC5\u987B\u540C\u5B9E\u4F8B\uFF08\u5168\u5C40\u54CD\u5E94\u6027\u3001getActivePinia\u3001\u8DEF\u7531\u6CE8\u5165\uFF09");
|
|
207
207
|
out.push("4. \u8FDC\u7A0B\u7684\u5168\u5C40\u526F\u4F5C\u7528\uFF08\u5168\u5C40\u7EC4\u4EF6/\u6307\u4EE4/\u542F\u52A8\u671F\u521D\u59CB\u5316\uFF09\u5C01\u88C5\u4E3A\u542F\u52A8\u5668\u6A21\u5757\u5E76 expose\uFF0C\u5BBF\u4E3B\u5728 loadRemote \u9875\u9762\u524D\u8C03\u7528\uFF1B");
|
|
208
|
-
out.push(" \u8DE8\u5E94\u7528\u5168\u5C40\u914D\u7F6E\uFF08locale/size \u7B49\uFF09\u7528\u8FD0\u884C\u65F6
|
|
209
|
-
out.push("5. \u8FDC\u7A0B\u9875\u9762\u53D6\u5BBF\u4E3B\u8FD0\u884C\u65F6\u4E00\u5F8B\u8D70 globalThis.
|
|
208
|
+
out.push(" \u8DE8\u5E94\u7528\u5168\u5C40\u914D\u7F6E\uFF08locale/size \u7B49\uFF09\u7528\u8FD0\u884C\u65F6 provideFulgurjsAppConfig / getFulgurjsAppConfig \u534F\u5546\uFF0C\u4E0D\u8981\u5404\u526F\u672C\u624B\u5DE5\u6CE8\u5165");
|
|
209
|
+
out.push("5. \u8FDC\u7A0B\u9875\u9762\u53D6\u5BBF\u4E3B\u8FD0\u884C\u65F6\u4E00\u5F8B\u8D70 globalThis.__FULGURJS_RUNTIME__ / getRuntime()\uFF0C\u7981\u6B62\u9759\u6001\u5BFC\u5165\u865A\u62DF\u8FD0\u884C\u65F6\uFF08DEV-008\uFF09");
|
|
210
210
|
out.push('6. dev \u51B7\u542F\u52A8\u9996\u8F6E 30~60s \u6709\u9884\u6784\u5EFA\u7A97\u53E3\uFF08\u77AC\u65F6 504/"ce"\uFF0CDEV-010\uFF09\uFF1A\u5148\u771F\u5B9E\u6253\u5F00\u9875\u9762\u9884\u70ED\u518D\u505A\u65AD\u8A00');
|
|
211
|
-
out.push("7. \u90E8\u7F72\u540E\u4F53\u68C0\
|
|
211
|
+
out.push("7. \u90E8\u7F72\u540E\u4F53\u68C0\uFF1Afulgurjs doctor --base <URL> --apps <\u5E94\u7528...>\uFF08\u7F13\u5B58\u5934/\u8D44\u6E90\u5F62\u6001/CORS/chunk \u53EF\u8FBE/\u7248\u672C skew\uFF09");
|
|
212
212
|
out.push("8. \u90E8\u7F72\u8BED\u4E49\uFF1AremoteEntry/manifest/index.html \u5FC5\u987B no-cache\uFF08\u4E25\u7981 immutable\uFF09\uFF1B\u5E26 hash \u7684 assets \u957F\u7F13\u5B58");
|
|
213
213
|
return out.join("\n");
|
|
214
214
|
}
|
|
@@ -217,13 +217,13 @@ var init_init = __esm({
|
|
|
217
217
|
"src/init.ts"() {
|
|
218
218
|
"use strict";
|
|
219
219
|
init_config();
|
|
220
|
-
MARK = "[
|
|
221
|
-
STARTER_CONFIG = `//
|
|
222
|
-
// \u7528\u6CD5\uFF1Anpx
|
|
223
|
-
// npx
|
|
224
|
-
import {
|
|
220
|
+
MARK = "[fulgurjs:init]";
|
|
221
|
+
STARTER_CONFIG = `// fulgurjs.config.ts \u2014\u2014 @fulgurjs/federation \u63A5\u5165\u914D\u7F6E\uFF08\u5355\u6587\u4EF6\u9A71\u52A8\uFF0C\u53EF\u5165\u5E93\u3001\u53EF\u590D\u8DD1\uFF09
|
|
222
|
+
// \u7528\u6CD5\uFF1Anpx fulgurjs init --config fulgurjs.config.ts \u6821\u9A8C\u914D\u7F6E\u5E76\u8F93\u51FA\u53EF\u7C98\u8D34\u6837\u677F\u4E0E\u6838\u5BF9\u6E05\u5355
|
|
223
|
+
// npx fulgurjs doctor --base http://<\u7AD9\u70B9> --apps <\u5E94\u7528\u76EE\u5F55\u540D...> \u90E8\u7F72\u4F53\u68C0
|
|
224
|
+
import { defineFulgurjsConfig } from '@fulgurjs/federation/config'
|
|
225
225
|
|
|
226
|
-
export default
|
|
226
|
+
export default defineFulgurjsConfig({
|
|
227
227
|
// \u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08monorepo \u6839\u6216\u5355\u5E94\u7528\u4ED3\u5E93\u6839\uFF09
|
|
228
228
|
root: process.cwd(),
|
|
229
229
|
apps: [
|
|
@@ -424,7 +424,7 @@ async function runDoctor(opts) {
|
|
|
424
424
|
const chunkSample = opts.chunkSample ?? 16;
|
|
425
425
|
for (const app of opts.apps) {
|
|
426
426
|
const root = `${opts.base.replace(/\/$/, "")}/${app.replace(/^\//, "")}`;
|
|
427
|
-
const entry = await checkStatus(`${root}/
|
|
427
|
+
const entry = await checkStatus(`${root}/fulgurjs-remoteEntry.js`, app, "fulgurjs-remoteEntry.js", {
|
|
428
428
|
expectJs: true,
|
|
429
429
|
expectNoCache: !opts.dev
|
|
430
430
|
});
|
|
@@ -440,7 +440,7 @@ async function runDoctor(opts) {
|
|
|
440
440
|
fix: acao ? void 0 : 'nginx \u5BF9 remoteEntry add_header Access-Control-Allow-Origin "*"'
|
|
441
441
|
});
|
|
442
442
|
}
|
|
443
|
-
const manifestRes = await checkStatus(`${root}/
|
|
443
|
+
const manifestRes = await checkStatus(`${root}/fulgurjs-manifest.json`, app, "fulgurjs-manifest.json", {
|
|
444
444
|
expectNoCache: !opts.dev
|
|
445
445
|
});
|
|
446
446
|
if (manifestRes.check) checks.push(manifestRes.check);
|
|
@@ -454,7 +454,7 @@ async function runDoctor(opts) {
|
|
|
454
454
|
app,
|
|
455
455
|
item: "manifest \u89E3\u6790",
|
|
456
456
|
level: "FAIL",
|
|
457
|
-
symptom: "
|
|
457
|
+
symptom: "fulgurjs-manifest.json \u4E0D\u662F\u5408\u6CD5 JSON",
|
|
458
458
|
cause: "\u4EA7\u7269\u4E0D\u5B8C\u6574\u6216\u88AB\u4E2D\u95F4\u5C42\u6539\u5199",
|
|
459
459
|
fix: "\u91CD\u65B0\u6784\u5EFA\u90E8\u7F72\uFF1B\u786E\u8BA4 nginx \u672A\u5BF9\u8BE5\u8DEF\u5F84\u505A sub/\u62FC\u63A5\u6539\u5199"
|
|
460
460
|
});
|
|
@@ -467,7 +467,7 @@ async function runDoctor(opts) {
|
|
|
467
467
|
htmlBody = html.res?.body ?? "";
|
|
468
468
|
}
|
|
469
469
|
if (opts.dev) {
|
|
470
|
-
const devEntry = await checkStatus(`${root}/@
|
|
470
|
+
const devEntry = await checkStatus(`${root}/@fulgurjs-entry.js`, app, "@fulgurjs-entry.js\uFF08dev \u5BB9\u5668\u5165\u53E3\uFF09", {
|
|
471
471
|
expectJs: true
|
|
472
472
|
});
|
|
473
473
|
if (devEntry.check) checks.push(devEntry.check);
|
|
@@ -549,7 +549,7 @@ async function runDoctor(opts) {
|
|
|
549
549
|
function formatDoctorReport(checks) {
|
|
550
550
|
const lines = [];
|
|
551
551
|
for (const c of checks) {
|
|
552
|
-
const head = `[
|
|
552
|
+
const head = `[fulgurjs:doctor] ${c.level} [${c.app}] ${c.item}`;
|
|
553
553
|
lines.push(c.level === "PASS" ? `${head} \u2014 ${c.symptom}` : `${head}
|
|
554
554
|
\u73B0\u8C61\uFF1A${c.symptom}`);
|
|
555
555
|
if (c.cause) lines.push(` \u6839\u56E0\uFF1A${c.cause}`);
|
|
@@ -558,25 +558,25 @@ function formatDoctorReport(checks) {
|
|
|
558
558
|
const fail = checks.filter((c) => c.level === "FAIL").length;
|
|
559
559
|
const warn = checks.filter((c) => c.level === "WARN").length;
|
|
560
560
|
const pass = checks.filter((c) => c.level === "PASS").length;
|
|
561
|
-
lines.push(`[
|
|
561
|
+
lines.push(`[fulgurjs:doctor] \u6C47\u603B\uFF1A${pass} PASS / ${warn} WARN / ${fail} FAIL`);
|
|
562
562
|
return lines.join("\n");
|
|
563
563
|
}
|
|
564
564
|
|
|
565
565
|
// src/cli.ts
|
|
566
|
-
var HELP = `
|
|
566
|
+
var HELP = `fulgurjs \u2014 Vite Module Federation CLI (@fulgurjs/federation)
|
|
567
567
|
|
|
568
568
|
\u7528\u6CD5\uFF1A
|
|
569
|
-
|
|
570
|
-
|
|
569
|
+
fulgurjs init [--template <path>] [--force] \u751F\u6210\u5E26\u6CE8\u91CA\u7684 fulgurjs.config.ts \u8D77\u6B65\u6A21\u677F
|
|
570
|
+
fulgurjs init --config <path> \u6821\u9A8C\u914D\u7F6E\uFF1B\u8F93\u51FA\u5404\u5E94\u7528 federation() \u7C98\u8D34\u5757\u3001
|
|
571
571
|
NGINX no-cache \u7AD9\u70B9\u6A21\u677F\u4E0E\u63A5\u5165\u6838\u5BF9\u6E05\u5355
|
|
572
|
-
|
|
573
|
-
|
|
572
|
+
fulgurjs doctor --base <URL> --apps <a,b,c> [--dev] [--json] [--chunk-sample N]
|
|
573
|
+
fulgurjs --help
|
|
574
574
|
|
|
575
575
|
\u793A\u4F8B\uFF1A
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
576
|
+
fulgurjs init # \u5F53\u524D\u76EE\u5F55\u5199 fulgurjs.config.ts\uFF08\u5DF2\u5B58\u5728\u5219\u62D2\u7EDD\uFF0C--force \u8986\u76D6\uFF09
|
|
577
|
+
fulgurjs init --config fulgurjs.config.ts # \u6821\u9A8C + \u8F93\u51FA\u6837\u677F
|
|
578
|
+
fulgurjs doctor --base http://your-site --apps app-a,app-b
|
|
579
|
+
fulgurjs doctor --base http://localhost:5173 --apps app-a --dev
|
|
580
580
|
`;
|
|
581
581
|
async function main() {
|
|
582
582
|
const argv = process.argv.slice(2);
|
|
@@ -602,25 +602,25 @@ async function main() {
|
|
|
602
602
|
return 2;
|
|
603
603
|
}
|
|
604
604
|
}
|
|
605
|
-
const target = resolve(argOf("--template") ?? "
|
|
605
|
+
const target = resolve(argOf("--template") ?? "fulgurjs.config.ts");
|
|
606
606
|
const result = await writeConfigTemplate2(target, has("--force"));
|
|
607
607
|
if (result === "exists") {
|
|
608
|
-
console.error(`[
|
|
608
|
+
console.error(`[fulgurjs:init] ${target} \u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6\uFF08--force \u5F3A\u5236\u8986\u76D6\uFF09`);
|
|
609
609
|
return 2;
|
|
610
610
|
}
|
|
611
|
-
console.log(`[
|
|
611
|
+
console.log(`[fulgurjs:init] \u5DF2\u751F\u6210\u8D77\u6B65\u6A21\u677F ${target}
|
|
612
612
|
\u540E\u7EED\u6B65\u9AA4\uFF1A
|
|
613
|
-
1. \u7F16\u8F91
|
|
614
|
-
2. npx
|
|
613
|
+
1. \u7F16\u8F91 fulgurjs.config.ts\uFF1A\u586B\u5165\u4F60\u7684\u5E94\u7528\u76EE\u5F55/\u5BB9\u5668\u540D/\u7AEF\u53E3/base/\u9875\u9762\u8DEF\u7531\u8868/exposes
|
|
614
|
+
2. npx fulgurjs init --config fulgurjs.config.ts # \u6821\u9A8C\u5E76\u8F93\u51FA\u53EF\u7C98\u8D34\u6837\u677F\u4E0E\u6838\u5BF9\u6E05\u5355
|
|
615
615
|
3. \u6309\u6E05\u5355\u628A federation() \u5757\u63A5\u5165\u5404\u5E94\u7528 vite.config.ts\uFF0C\u5B89\u88C5\u4F9D\u8D56
|
|
616
|
-
4. \u90E8\u7F72\u540E\uFF1Anpx
|
|
616
|
+
4. \u90E8\u7F72\u540E\uFF1Anpx fulgurjs doctor --base <URL> --apps <\u5E94\u7528...>`);
|
|
617
617
|
return 0;
|
|
618
618
|
}
|
|
619
619
|
if (cmd === "doctor") {
|
|
620
620
|
const base = argOf("--base");
|
|
621
621
|
const appsRaw = argOf("--apps") ?? "main";
|
|
622
622
|
if (!base) {
|
|
623
|
-
console.error("[
|
|
623
|
+
console.error("[fulgurjs:doctor] \u7F3A\u5C11 --base <URL>\uFF08\u7AD9\u70B9\u6839\u5730\u5740\uFF0C\u5982 http://your-site\uFF09");
|
|
624
624
|
return 2;
|
|
625
625
|
}
|
|
626
626
|
const apps = appsRaw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -644,7 +644,7 @@ ${HELP}`);
|
|
|
644
644
|
main().then(
|
|
645
645
|
(code) => process.exit(code),
|
|
646
646
|
(e) => {
|
|
647
|
-
console.error("[
|
|
647
|
+
console.error("[fulgurjs] \u6267\u884C\u5931\u8D25\uFF1A", e);
|
|
648
648
|
process.exit(2);
|
|
649
649
|
}
|
|
650
650
|
);
|