generator-mico-cli 0.2.21 → 0.2.23
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/README.md +33 -0
- package/bin/mico.js +15 -2
- package/generators/micro-react/index.js +44 -6
- package/generators/micro-react/meta.json +2 -1
- package/generators/micro-react/templates/.cursor/rules/always-read-docs.mdc +14 -4
- package/generators/micro-react/templates/.cursor/rules/layout-app.mdc +36 -26
- package/generators/micro-react/templates/.cursor/rules/project-overview.mdc +5 -2
- package/generators/micro-react/templates/CLAUDE.md +4 -2
- package/generators/micro-react/templates/_gitignore +3 -1
- package/generators/micro-react/templates/_npmrc +1 -0
- package/generators/micro-react/templates/apps/layout/config/config.dev.ts +7 -3
- package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +5 -0
- package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +5 -0
- package/generators/micro-react/templates/apps/layout/config/config.prod.ts +12 -0
- package/generators/micro-react/templates/apps/layout/config/routes.ts +0 -5
- package/generators/micro-react/templates/apps/layout/docs/feature-/345/276/256/345/211/215/347/253/257/346/250/241/345/274/217.md +4 -2
- package/generators/micro-react/templates/apps/layout/docs/feature-/350/217/234/345/215/225/346/235/203/351/231/220/346/216/247/345/210/266.md +116 -56
- package/generators/micro-react/templates/apps/layout/docs/feature-/350/267/257/347/224/261/344/270/216/350/217/234/345/215/225/350/247/243/350/200/246.md +179 -0
- package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +81 -61
- package/generators/micro-react/templates/apps/layout/mock/menus.ts +89 -144
- package/generators/micro-react/templates/apps/layout/mock/pages.ts +83 -0
- package/generators/micro-react/templates/apps/layout/package.json +1 -0
- package/generators/micro-react/templates/apps/layout/src/app.tsx +13 -8
- package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +118 -43
- package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +31 -4
- package/generators/micro-react/templates/apps/layout/src/common/micro-prefetch.ts +3 -2
- package/generators/micro-react/templates/apps/layout/src/common/portal-data.ts +45 -0
- package/generators/micro-react/templates/apps/layout/src/common/request/config.ts +49 -10
- package/generators/micro-react/templates/apps/layout/src/common/request/interceptors.ts +1 -1
- package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +6 -0
- package/generators/micro-react/templates/apps/layout/src/common/theme.ts +0 -2
- package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.less +0 -1
- package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.tsx +4 -4
- package/generators/micro-react/templates/apps/layout/src/components/IconFont/index.tsx +4 -5
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.less +21 -6
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +4 -3
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/micro-app-manager.ts +7 -1
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/AvatarDropdown.tsx +12 -16
- package/generators/micro-react/templates/apps/layout/src/global.less +15 -2
- package/generators/micro-react/templates/apps/layout/src/hooks/useMenu.ts +3 -2
- package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.less +32 -4
- package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +20 -10
- package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +75 -38
- package/generators/micro-react/templates/apps/layout/src/pages/404/index.tsx +3 -7
- package/generators/micro-react/templates/apps/layout/src/services/user.ts +7 -3
- package/generators/micro-react/templates/dev.preset.json +1 -1
- package/generators/micro-react/templates/package.json +1 -0
- package/generators/micro-react/templates/scripts/apply-sentry-plugin.ts +45 -0
- package/generators/subapp-react/index.js +206 -6
- package/generators/subapp-react/templates/homepage/.env +2 -1
- package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +1 -0
- package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +1 -0
- package/generators/subapp-react/templates/homepage/config/config.prod.ts +8 -0
- package/generators/subapp-react/templates/homepage/package.json +1 -0
- package/generators/subapp-react/templates/homepage/src/app.tsx +6 -0
- package/generators/subapp-umd/ignore-list.json +5 -0
- package/generators/subapp-umd/index.js +325 -0
- package/generators/subapp-umd/meta.json +11 -0
- package/generators/subapp-umd/templates/README.md +94 -0
- package/generators/subapp-umd/templates/package.json +35 -0
- package/generators/subapp-umd/templates/public/index.html +34 -0
- package/generators/subapp-umd/templates/src/App.less +15 -0
- package/generators/subapp-umd/templates/src/App.tsx +13 -0
- package/generators/subapp-umd/templates/src/index.ts +2 -0
- package/generators/subapp-umd/templates/tsconfig.json +27 -0
- package/generators/subapp-umd/templates/webpack.config.js +68 -0
- package/lib/utils.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
| [docs/mico-cli.md](docs/mico-cli.md) | Mico CLI 功能概述与技术方案 |
|
|
10
10
|
| [docs/micro-react-generator.md](docs/micro-react-generator.md) | Monorepo 项目生成器说明 |
|
|
11
11
|
| [docs/subapp-react-generator.md](docs/subapp-react-generator.md) | React 子应用生成器说明 |
|
|
12
|
+
| [docs/subapp-umd-generator.md](docs/subapp-umd-generator.md) | UMD 组件包生成器说明 |
|
|
12
13
|
|
|
13
14
|
## 要求
|
|
14
15
|
|
|
@@ -97,6 +98,7 @@ mico create micro-react
|
|
|
97
98
|
- @mico-platform/ui、@mico-platform/theme
|
|
98
99
|
- Turborepo + pnpm Workspace
|
|
99
100
|
- Husky + Commitlint
|
|
101
|
+
- @common-web/sentry 错误监控与 SourceMap 上传
|
|
100
102
|
|
|
101
103
|
## React 子应用生成器
|
|
102
104
|
|
|
@@ -108,6 +110,34 @@ cd <monorepo-root>
|
|
|
108
110
|
mico create subapp-react
|
|
109
111
|
```
|
|
110
112
|
|
|
113
|
+
## UMD 组件包生成器
|
|
114
|
+
|
|
115
|
+
在 Monorepo 的 `packages/` 目录下创建 UMD 格式的组件包,使用 Webpack 构建。适用于通过 `<script>` 标签加载的场景(如主应用菜单挂载组件、第三方系统嵌入 Widget 等)。
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cd <monorepo-root>
|
|
119
|
+
mico create subapp-umd
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
生成器会提示输入:
|
|
123
|
+
- **Package name** — 包名(如 `my-widget`)
|
|
124
|
+
- **UMD global variable name** — 全局变量名(如 `MyWidget`)
|
|
125
|
+
- **Package scope** — 包作用域(自动从根 `package.json` 检测)
|
|
126
|
+
- **Dev server port** — 开发端口(默认 `9100`)
|
|
127
|
+
|
|
128
|
+
生成的包支持:
|
|
129
|
+
- `pnpm dev` — 启动 webpack-dev-server,同时提供 HTML 预览页和 UMD JS 文件
|
|
130
|
+
- `pnpm build` — 构建生产环境 UMD 产物到 `dist/`
|
|
131
|
+
|
|
132
|
+
开发模式下:
|
|
133
|
+
|
|
134
|
+
| URL | 用途 |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `http://localhost:<port>/` | HTML 预览页,独立调试 |
|
|
137
|
+
| `http://localhost:<port>/<name>.umd.js` | UMD JS 文件,供主应用通过 `jsUrls` 联调 |
|
|
138
|
+
|
|
139
|
+
DevTools Sources 面板中可在 `webpack://<name>/src/` 下定位原始 TypeScript 源码进行断点调试。
|
|
140
|
+
|
|
111
141
|
## 本地调试
|
|
112
142
|
|
|
113
143
|
克隆项目后,执行以下步骤进行本地开发和调试:
|
|
@@ -133,6 +163,9 @@ mico create micro-react
|
|
|
133
163
|
|
|
134
164
|
# 测试 subapp-react 生成器(需在已有 monorepo 中执行)
|
|
135
165
|
mico create subapp-react
|
|
166
|
+
|
|
167
|
+
# 测试 subapp-umd 生成器(需在已有 monorepo 中执行)
|
|
168
|
+
mico create subapp-umd
|
|
136
169
|
```
|
|
137
170
|
|
|
138
171
|
调试完成后,可以取消全局链接:
|
package/bin/mico.js
CHANGED
|
@@ -29,12 +29,14 @@ Options:
|
|
|
29
29
|
--version, -v Show version number
|
|
30
30
|
--verbose Show detailed output during generation
|
|
31
31
|
--dry-run Preview files without creating them
|
|
32
|
+
--force Overwrite all existing files without confirmation
|
|
32
33
|
--no-update-check Skip update check
|
|
33
34
|
|
|
34
35
|
Examples:
|
|
35
36
|
mico create subapp-react
|
|
36
37
|
mico create micro-react --verbose
|
|
37
38
|
mico create micro-react --dry-run
|
|
39
|
+
mico create micro-react --force
|
|
38
40
|
mico list
|
|
39
41
|
mico update
|
|
40
42
|
mico doctor
|
|
@@ -350,6 +352,7 @@ function performUpdate(latestVersion) {
|
|
|
350
352
|
* @param {object} options - 选项
|
|
351
353
|
* @param {boolean} options.verbose - 是否启用详细输出
|
|
352
354
|
* @param {boolean} options.dryRun - 是否启用 dry-run 模式
|
|
355
|
+
* @param {boolean} options.force - 是否强制覆盖已有文件
|
|
353
356
|
*/
|
|
354
357
|
function runGenerator(generator, rest, passthroughArgs, options = {}) {
|
|
355
358
|
const localGeneratorEntry = path.join(
|
|
@@ -374,6 +377,10 @@ function runGenerator(generator, rest, passthroughArgs, options = {}) {
|
|
|
374
377
|
yoArgs.push('--dry-run');
|
|
375
378
|
}
|
|
376
379
|
|
|
380
|
+
if (options.force) {
|
|
381
|
+
yoArgs.push('--force');
|
|
382
|
+
}
|
|
383
|
+
|
|
377
384
|
if (passthroughArgs.length > 0) {
|
|
378
385
|
yoArgs.push('--', ...passthroughArgs);
|
|
379
386
|
}
|
|
@@ -394,6 +401,9 @@ function runGenerator(generator, rest, passthroughArgs, options = {}) {
|
|
|
394
401
|
if (options.dryRun) {
|
|
395
402
|
console.log(' \x1b[2m[verbose] Dry-run mode enabled\x1b[0m');
|
|
396
403
|
}
|
|
404
|
+
if (options.force) {
|
|
405
|
+
console.log(' \x1b[2m[verbose] Force mode enabled\x1b[0m');
|
|
406
|
+
}
|
|
397
407
|
console.log('');
|
|
398
408
|
}
|
|
399
409
|
|
|
@@ -432,6 +442,7 @@ async function main() {
|
|
|
432
442
|
const skipUpdateCheck = mainArgs.includes('--no-update-check');
|
|
433
443
|
const isVerbose = mainArgs.includes('--verbose');
|
|
434
444
|
const isDryRun = mainArgs.includes('--dry-run');
|
|
445
|
+
const isForce = mainArgs.includes('--force');
|
|
435
446
|
|
|
436
447
|
// 过滤掉标志参数
|
|
437
448
|
const filteredArgs = mainArgs.filter(
|
|
@@ -442,7 +453,8 @@ async function main() {
|
|
|
442
453
|
arg !== '-v' &&
|
|
443
454
|
arg !== '--no-update-check' &&
|
|
444
455
|
arg !== '--verbose' &&
|
|
445
|
-
arg !== '--dry-run'
|
|
456
|
+
arg !== '--dry-run' &&
|
|
457
|
+
arg !== '--force'
|
|
446
458
|
);
|
|
447
459
|
|
|
448
460
|
// 处理 --version
|
|
@@ -514,7 +526,8 @@ async function main() {
|
|
|
514
526
|
// 运行生成器
|
|
515
527
|
runGenerator(generator, rest.slice(1), passthroughArgs, {
|
|
516
528
|
verbose: isVerbose,
|
|
517
|
-
dryRun: isDryRun
|
|
529
|
+
dryRun: isDryRun,
|
|
530
|
+
force: isForce
|
|
518
531
|
});
|
|
519
532
|
return;
|
|
520
533
|
}
|
|
@@ -36,9 +36,9 @@ module.exports = class extends Generator {
|
|
|
36
36
|
this.logger.verbose('Config:', JSON.stringify(rcConfig, null, 2));
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
// 检查当前目录是否已是一个 monorepo
|
|
39
|
+
// 检查当前目录是否已是一个 monorepo(--force 跳过此检查)
|
|
40
40
|
const workspaceFile = path.join(this.projectRoot, 'pnpm-workspace.yaml');
|
|
41
|
-
if (fs.existsSync(workspaceFile)) {
|
|
41
|
+
if (fs.existsSync(workspaceFile) && !this.options.force) {
|
|
42
42
|
console.error('');
|
|
43
43
|
console.error('❌ Error: Current directory is already a monorepo.');
|
|
44
44
|
console.error('');
|
|
@@ -51,6 +51,9 @@ module.exports = class extends Generator {
|
|
|
51
51
|
console.error(' mkdir my-project && cd my-project');
|
|
52
52
|
console.error(' mico create micro-react');
|
|
53
53
|
console.error('');
|
|
54
|
+
console.error(' To regenerate in an existing monorepo, use --force:');
|
|
55
|
+
console.error(' mico create micro-react --force');
|
|
56
|
+
console.error('');
|
|
54
57
|
process.exit(1);
|
|
55
58
|
}
|
|
56
59
|
}
|
|
@@ -278,9 +281,31 @@ module.exports = class extends Generator {
|
|
|
278
281
|
|
|
279
282
|
this.log('');
|
|
280
283
|
this.log('📦 正在安装依赖...');
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
+
try {
|
|
285
|
+
this.spawnCommandSync('pnpm', ['install'], {
|
|
286
|
+
cwd: this.destDir,
|
|
287
|
+
});
|
|
288
|
+
} catch (e) {
|
|
289
|
+
this._installFailed = true;
|
|
290
|
+
this.log('');
|
|
291
|
+
this.log('⚠️ 依赖安装失败,但项目文件已全部生成。');
|
|
292
|
+
this.logger.verbose('Install error:', e.message);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// 依赖安装成功后,格式化生成的文件以消除风格差异
|
|
297
|
+
const layoutDir = path.join(this.destDir, 'apps/layout');
|
|
298
|
+
if (fs.existsSync(path.join(layoutDir, '.prettierrc'))) {
|
|
299
|
+
this.log('');
|
|
300
|
+
this.log('🎨 格式化生成的文件...');
|
|
301
|
+
try {
|
|
302
|
+
this.spawnCommandSync('pnpm', ['-C', 'apps/layout', 'format'], {
|
|
303
|
+
cwd: this.destDir,
|
|
304
|
+
});
|
|
305
|
+
} catch (e) {
|
|
306
|
+
this.logger.verbose('Formatting failed (non-critical):', e.message);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
284
309
|
}
|
|
285
310
|
|
|
286
311
|
end() {
|
|
@@ -288,7 +313,20 @@ module.exports = class extends Generator {
|
|
|
288
313
|
if (this._skipInstall) return;
|
|
289
314
|
|
|
290
315
|
this.log('');
|
|
291
|
-
|
|
316
|
+
|
|
317
|
+
if (this._installFailed) {
|
|
318
|
+
this.log('⚠️ 项目文件已创建,但依赖安装未完成。');
|
|
319
|
+
this.log('');
|
|
320
|
+
this.log(' 请手动安装依赖:');
|
|
321
|
+
this.log('');
|
|
322
|
+
this.log(' pnpm install');
|
|
323
|
+
this.log('');
|
|
324
|
+
this.log(' 如果安装仍然失败,可尝试:');
|
|
325
|
+
this.log(' pnpm install --network-concurrency 4');
|
|
326
|
+
} else {
|
|
327
|
+
this.log('✅ 项目创建成功!');
|
|
328
|
+
}
|
|
329
|
+
|
|
292
330
|
this.log('');
|
|
293
331
|
this.log(' 后续步骤:');
|
|
294
332
|
this.log('');
|
|
@@ -20,8 +20,15 @@ docs/
|
|
|
20
20
|
### 2. Layout 应用文档 (`/apps/layout/docs/`)
|
|
21
21
|
```
|
|
22
22
|
apps/layout/docs/
|
|
23
|
-
├── feature-微前端模式.md
|
|
24
|
-
|
|
23
|
+
├── feature-微前端模式.md # qiankun 微前端架构
|
|
24
|
+
├── feature-路由与菜单解耦.md # PAGES/MENUS 数据源分离、双层权限
|
|
25
|
+
├── feature-菜单权限控制.md # sideMenus 白名单、认证与授权分离
|
|
26
|
+
├── feature-主题色切换.md # 主题系统实现
|
|
27
|
+
├── feature-404页面.md # 404 页面
|
|
28
|
+
├── arch-请求模块.md # HTTP 请求层模块化设计
|
|
29
|
+
├── arch-日志与常量.md # Logger 工具与常量管理
|
|
30
|
+
├── common-intl.md # 国际化公共包
|
|
31
|
+
└── utils-timezone.md # 时区工具
|
|
25
32
|
```
|
|
26
33
|
|
|
27
34
|
### 3. 其他应用文档
|
|
@@ -33,8 +40,9 @@ apps/layout/docs/
|
|
|
33
40
|
|
|
34
41
|
### Step 1: 确认需求涉及的模块
|
|
35
42
|
- 微前端相关 → 阅读 `apps/layout/docs/feature-微前端模式.md`
|
|
43
|
+
- 路由/菜单/权限相关 → 阅读 `apps/layout/docs/feature-路由与菜单解耦.md` 和 `apps/layout/docs/feature-菜单权限控制.md`
|
|
36
44
|
- 主题/样式相关 → 阅读 `apps/layout/docs/feature-主题色切换.md`
|
|
37
|
-
- 请求/认证相关 → 阅读 `
|
|
45
|
+
- 请求/认证相关 → 阅读 `apps/layout/docs/arch-请求模块.md` 和 `src/common/auth/` 源码
|
|
38
46
|
- 菜单相关 → 阅读 `src/common/menu/` 源码
|
|
39
47
|
|
|
40
48
|
### Step 2: 查找相关文档
|
|
@@ -54,9 +62,11 @@ find . -name "*.md" -type f | grep -v node_modules
|
|
|
54
62
|
| 需求类型 | 必读文档 |
|
|
55
63
|
|---------|---------|
|
|
56
64
|
| 新建子应用 | `apps/layout/docs/feature-微前端模式.md` |
|
|
65
|
+
| 路由/页面配置 | `apps/layout/docs/feature-路由与菜单解耦.md` |
|
|
66
|
+
| 权限控制 | `apps/layout/docs/feature-菜单权限控制.md` |
|
|
57
67
|
| 主题适配 | `apps/layout/docs/feature-主题色切换.md` |
|
|
58
68
|
| 提交代码 | `docs/commit-message.md` |
|
|
59
|
-
| API 请求 | `
|
|
69
|
+
| API 请求 | `apps/layout/docs/arch-请求模块.md` |
|
|
60
70
|
| 认证登录 | `src/common/auth/` 目录源码 |
|
|
61
71
|
| 菜单配置 | `src/common/menu/types.ts` 类型定义 |
|
|
62
72
|
|
|
@@ -63,24 +63,27 @@ apps/layout/
|
|
|
63
63
|
const BasicLayout: React.FC = () => {
|
|
64
64
|
const location = useLocation();
|
|
65
65
|
|
|
66
|
-
//
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
return extractRoutes(menus);
|
|
66
|
+
// 所有页面路由(优先 PAGES,降级 MENUS)— 用于路由匹配和渲染
|
|
67
|
+
const allPageRoutes = useMemo(() => {
|
|
68
|
+
return getDynamicRoutes();
|
|
70
69
|
}, []);
|
|
71
70
|
|
|
72
|
-
//
|
|
71
|
+
// 菜单路由(从 MENUS)— 用于权限交叉引用
|
|
72
|
+
const allMenuRoutes = useMemo(() => {
|
|
73
|
+
return extractRoutes(getMenus());
|
|
74
|
+
}, []);
|
|
75
|
+
|
|
76
|
+
// 当前路由配置(从所有页面路由中查找)
|
|
73
77
|
const currentRoute = useMemo(() => {
|
|
74
|
-
return findRouteByPath(
|
|
75
|
-
}, [
|
|
78
|
+
return findRouteByPath(allPageRoutes, location.pathname);
|
|
79
|
+
}, [allPageRoutes, location.pathname]);
|
|
76
80
|
|
|
77
81
|
// 渲染页面内容
|
|
78
82
|
const renderContent = () => {
|
|
79
|
-
// 微应用类型使用 MicroAppLoader
|
|
80
83
|
if (currentRoute?.loadType === 'microapp' && currentRoute.entry) {
|
|
81
|
-
|
|
84
|
+
const appName = getAppNameFromEntry(currentRoute.entry);
|
|
85
|
+
return <MicroAppLoader entry={currentRoute.entry} name={appName} />;
|
|
82
86
|
}
|
|
83
|
-
// 内部路由使用 Outlet
|
|
84
87
|
return <Outlet />;
|
|
85
88
|
};
|
|
86
89
|
|
|
@@ -98,28 +101,36 @@ const BasicLayout: React.FC = () => {
|
|
|
98
101
|
};
|
|
99
102
|
```
|
|
100
103
|
|
|
101
|
-
### 2. 菜单系统 (common/menu/)
|
|
104
|
+
### 2. 全局数据源 (common/portal-data.ts) + 菜单系统 (common/menu/)
|
|
102
105
|
|
|
103
106
|
```typescript
|
|
104
|
-
//
|
|
105
|
-
const
|
|
107
|
+
// 获取页面列表 (window.__MICO_PAGES__)
|
|
108
|
+
const pages = getPages();
|
|
109
|
+
|
|
110
|
+
// 获取菜单树 (window.__MICO_MENUS__)
|
|
111
|
+
const menus = getMenus();
|
|
106
112
|
|
|
107
|
-
//
|
|
108
|
-
const routes =
|
|
113
|
+
// 从页面列表提取动态路由(优先数据源)
|
|
114
|
+
const routes = getDynamicRoutes();
|
|
109
115
|
|
|
110
|
-
//
|
|
116
|
+
// 从菜单树提取路由(用于权限交叉引用)
|
|
117
|
+
const menuRoutes = extractRoutes(menus);
|
|
118
|
+
|
|
119
|
+
// 解析菜单项(用于侧边栏渲染)
|
|
111
120
|
const menuItems = parseMenuItems(menus);
|
|
112
121
|
|
|
113
122
|
// 查找当前路由
|
|
114
123
|
const currentRoute = findRouteByPath(routes, pathname);
|
|
124
|
+
|
|
125
|
+
// 通过 pageId 查找页面(O(1))
|
|
126
|
+
const page = getPageById(pageId);
|
|
115
127
|
```
|
|
116
128
|
|
|
117
129
|
### 3. 动态路由 (app.tsx)
|
|
118
130
|
|
|
119
131
|
```typescript
|
|
120
132
|
export function patchClientRoutes({ routes }: { routes: any[] }) {
|
|
121
|
-
const
|
|
122
|
-
const dynamicRoutes = extractRoutes(menus);
|
|
133
|
+
const dynamicRoutes = getDynamicRoutes(); // 从 __MICO_PAGES__ 获取
|
|
123
134
|
|
|
124
135
|
const rootRoute = routes.find((r) => r.path === '/');
|
|
125
136
|
dynamicRoutes.forEach((route) => {
|
|
@@ -128,9 +139,7 @@ export function patchClientRoutes({ routes }: { routes: any[] }) {
|
|
|
128
139
|
name: route.name,
|
|
129
140
|
meta: {
|
|
130
141
|
loadType: route.loadType,
|
|
131
|
-
|
|
132
|
-
jsUrls: route.jsUrls,
|
|
133
|
-
cssUrls: route.cssUrls,
|
|
142
|
+
entry: route.entry,
|
|
134
143
|
},
|
|
135
144
|
});
|
|
136
145
|
});
|
|
@@ -265,8 +274,9 @@ const { collapsed } = useModel('global');
|
|
|
265
274
|
|
|
266
275
|
## 注意事项
|
|
267
276
|
|
|
268
|
-
1.
|
|
269
|
-
2. **路由动态生成**: 在 `patchClientRoutes`
|
|
270
|
-
3.
|
|
271
|
-
4.
|
|
272
|
-
5.
|
|
277
|
+
1. **数据来源**: 页面列表通过 `window.__MICO_PAGES__` 注入,菜单树通过 `window.__MICO_MENUS__` 注入
|
|
278
|
+
2. **路由动态生成**: 在 `patchClientRoutes` 中优先从 `__MICO_PAGES__` 生成路由
|
|
279
|
+
3. **权限交叉引用**: 菜单路由(`__MICO_MENUS__`)用于权限判断,页面路由(`__MICO_PAGES__`)用于渲染
|
|
280
|
+
4. **微应用判断**: 根据 `htmlUrl` 或 `jsUrls` 判断是否为微应用
|
|
281
|
+
5. **主题初始化**: 在 `app.tsx` 中调用 `initTheme()` 避免闪烁
|
|
282
|
+
6. **认证共享**: 子应用使用主应用传递的 `request` 实例
|
|
@@ -61,15 +61,16 @@ alwaysApply: true
|
|
|
61
61
|
- **关键文件**:
|
|
62
62
|
- `src/layouts/index.tsx` - 主布局组件
|
|
63
63
|
- `src/components/MicroAppLoader/` - 微应用加载器
|
|
64
|
-
- `src/common/menu/parser.ts` -
|
|
64
|
+
- `src/common/menu/parser.ts` - 菜单解析、页面数据提取与路由生成
|
|
65
65
|
- `src/common/request/index.ts` - 统一请求封装
|
|
66
66
|
- `src/hooks/useTheme.ts` - 主题管理 Hook
|
|
67
67
|
|
|
68
68
|
### 2. 微前端架构
|
|
69
|
-
-
|
|
69
|
+
- 路由注册优先使用 `window.__MICO_PAGES__`(页面列表),无数据时降级到 `window.__MICO_MENUS__`(菜单树)
|
|
70
70
|
- 根据 `htmlUrl` 或 `jsUrls` 判断是否为微应用
|
|
71
71
|
- 使用 `loadMicroApp` API 动态挂载子应用
|
|
72
72
|
- 子应用共享主应用的 `request` 实例
|
|
73
|
+
- 权限通过菜单交叉引用 + 页面级兜底的双层策略控制
|
|
73
74
|
|
|
74
75
|
### 3. 主题系统
|
|
75
76
|
- 支持亮色/暗黑主题切换
|
|
@@ -123,6 +124,8 @@ Jenkins 根据环境执行 `CICD/` 下的构建脚本:
|
|
|
123
124
|
## 相关文档
|
|
124
125
|
|
|
125
126
|
- [微前端模式](mdc:apps/layout/docs/feature-微前端模式.md)
|
|
127
|
+
- [路由与菜单解耦](mdc:apps/layout/docs/feature-路由与菜单解耦.md)
|
|
128
|
+
- [菜单权限控制](mdc:apps/layout/docs/feature-菜单权限控制.md)
|
|
126
129
|
- [主题色切换](mdc:apps/layout/docs/feature-主题色切换.md)
|
|
127
130
|
- [提交规范](mdc:docs/commit-message.md)
|
|
128
131
|
- [部署说明](mdc:deployDesc.md)
|
|
@@ -108,8 +108,8 @@ Logger 工具在 `src/common/logger.ts`,常量定义在 `src/constants/index.t
|
|
|
108
108
|
### 认证模块
|
|
109
109
|
认证逻辑在 `src/common/auth/`,核心文件 `auth-manager.ts` 管理 Token 存储和用户信息。SSO 登录在 `getInitialState()` 中完成,确保 UI 渲染前认证已就绪。
|
|
110
110
|
|
|
111
|
-
###
|
|
112
|
-
菜单解析与类型定义在 `src/common/menu
|
|
111
|
+
### 菜单与路由系统
|
|
112
|
+
菜单解析与类型定义在 `src/common/menu/`。路由注册消费 `window.__MICO_PAGES__`(页面列表),菜单栏消费 `window.__MICO_MENUS__`(菜单树),两者解耦运作。权限通过菜单交叉引用 + 页面级兜底的双层策略控制。详见 [路由与菜单解耦](./apps/layout/docs/feature-路由与菜单解耦.md) 和 [菜单权限控制](./apps/layout/docs/feature-菜单权限控制.md)。
|
|
113
113
|
|
|
114
114
|
### 微前端
|
|
115
115
|
layout 应用作为 qiankun 主应用,子应用通过 Umi 配置中的 qiankun 配置注册。详见 [微前端模式](./apps/layout/docs/feature-微前端模式.md)。
|
|
@@ -121,6 +121,8 @@ layout 应用作为 qiankun 主应用,子应用通过 Umi 配置中的 qiankun
|
|
|
121
121
|
| [README.md](./README.md) | 项目入口、技术栈、常用命令 |
|
|
122
122
|
| [提交规范](./docs/commit-message.md) | Git Commit 详细规范 |
|
|
123
123
|
| [微前端模式](./apps/layout/docs/feature-微前端模式.md) | qiankun 架构、MicroAppLoader、子应用配置 |
|
|
124
|
+
| [路由与菜单解耦](./apps/layout/docs/feature-路由与菜单解耦.md) | PAGES/MENUS 数据源分离、双层权限控制 |
|
|
125
|
+
| [菜单权限控制](./apps/layout/docs/feature-菜单权限控制.md) | sideMenus 白名单、认证与授权分离 |
|
|
124
126
|
| [主题色切换](./apps/layout/docs/feature-主题色切换.md) | useTheme Hook、CSS 变量系统 |
|
|
125
127
|
| [请求模块架构](./apps/layout/docs/arch-请求模块.md) | HTTP 请求层模块化设计 |
|
|
126
128
|
| [日志与常量](./apps/layout/docs/arch-日志与常量.md) | Logger 工具与常量管理 |
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
registry=https://registry.npmjs.com/
|
|
2
2
|
@mico-platform:registry=https://nexus-vywrajy.micoworld.net/repository/mico-base-common/
|
|
3
|
+
@common-web:registry=https://nexus-vywrajy.micoworld.net/repository/mico-base-common/
|
|
3
4
|
package-lock=false
|
|
4
5
|
//nexus-vywrajy.micoworld.net/repository/mico-base-common/:_auth=bWljby1ucG06SDR4WUROazdad1NeczltblJMTw==
|
|
5
6
|
|
|
@@ -4,6 +4,7 @@ import { defineConfig } from '@umijs/max';
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
import mockMenus from '../mock/menus';
|
|
7
|
+
import mockPages from '../mock/pages';
|
|
7
8
|
|
|
8
9
|
const config: ReturnType<typeof defineConfig> = {
|
|
9
10
|
publicPath: '/',
|
|
@@ -16,18 +17,21 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
16
17
|
{
|
|
17
18
|
content: `
|
|
18
19
|
window.__MICO_MENUS__ = ${JSON.stringify(mockMenus)};
|
|
20
|
+
window.__MICO_PAGES__ = ${JSON.stringify(mockPages)};
|
|
19
21
|
window.__MICO_CONFIG__ = {
|
|
20
22
|
appName: '<%= projectName %>',
|
|
23
|
+
title: '测试样例',
|
|
24
|
+
logo: '',
|
|
21
25
|
apiBaseUrl: '',
|
|
22
26
|
defaultPath: '',
|
|
23
27
|
// 免认证路由(跳过 SSO 登录),支持 /* 前缀匹配
|
|
24
28
|
// noAuthRouteList: ['/*'],
|
|
25
29
|
// 免权限校验路由(跳过菜单权限检查)
|
|
26
|
-
|
|
30
|
+
noPermissionRouteList: [],
|
|
27
31
|
// 不显示布局的路由(全屏页面)
|
|
28
|
-
// noLayoutRouteList: [
|
|
32
|
+
// noLayoutRouteList: [],
|
|
29
33
|
// 关闭权限控制(调试用)
|
|
30
|
-
disableAuth:
|
|
34
|
+
disableAuth: false,
|
|
31
35
|
};
|
|
32
36
|
`,
|
|
33
37
|
},
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
import { defineConfig } from '@umijs/max';
|
|
4
4
|
|
|
5
5
|
const config: ReturnType<typeof defineConfig> = {
|
|
6
|
+
externals: {
|
|
7
|
+
react: 'React',
|
|
8
|
+
'react-dom': 'ReactDOM',
|
|
9
|
+
'@common-web/sentry': 'CommonWebSentry',
|
|
10
|
+
},
|
|
6
11
|
define: {
|
|
7
12
|
'process.env.NODE_ENV': 'development',
|
|
8
13
|
'process.env.APP_ID': '<%= projectName %>',
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
import { defineConfig } from '@umijs/max';
|
|
4
4
|
|
|
5
5
|
const config: ReturnType<typeof defineConfig> = {
|
|
6
|
+
externals: {
|
|
7
|
+
react: 'React',
|
|
8
|
+
'react-dom': 'ReactDOM',
|
|
9
|
+
'@common-web/sentry': 'CommonWebSentry',
|
|
10
|
+
},
|
|
6
11
|
define: {
|
|
7
12
|
'process.env.NODE_ENV': 'testing',
|
|
8
13
|
'process.env.APP_ID': '<%= projectName %>',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// https://umijs.org/config/
|
|
2
2
|
|
|
3
3
|
import { defineConfig } from '@umijs/max';
|
|
4
|
+
import { applySentryPlugin } from '../../../scripts/apply-sentry-plugin';
|
|
4
5
|
const { CDN_PUBLIC_PATH } = process.env;
|
|
5
6
|
|
|
6
7
|
const PUBLIC_PATH: string = CDN_PUBLIC_PATH
|
|
@@ -8,6 +9,11 @@ const PUBLIC_PATH: string = CDN_PUBLIC_PATH
|
|
|
8
9
|
: '/layout/';
|
|
9
10
|
|
|
10
11
|
const config: ReturnType<typeof defineConfig> = {
|
|
12
|
+
/**
|
|
13
|
+
* 启用 Source Map(用于 Sentry 错误追踪)
|
|
14
|
+
* hidden-source-map 会生成 .map 文件但不在 JS 中添加 sourcemap 注释
|
|
15
|
+
*/
|
|
16
|
+
devtool: 'hidden-source-map',
|
|
11
17
|
define: {
|
|
12
18
|
'process.env.NODE_ENV': 'production',
|
|
13
19
|
'process.env.APP_ID': '<%= projectName %>',
|
|
@@ -20,6 +26,11 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
20
26
|
'process.env.EXTERNAL_LOGIN_PATH':
|
|
21
27
|
'https://micous-idp.cig.tencentcs.com/sso/xxxxxxx/cas',
|
|
22
28
|
},
|
|
29
|
+
externals: {
|
|
30
|
+
react: 'React',
|
|
31
|
+
'react-dom': 'ReactDOM',
|
|
32
|
+
'@common-web/sentry': 'CommonWebSentry',
|
|
33
|
+
},
|
|
23
34
|
// 生产环境:将所有代码打包到一个文件
|
|
24
35
|
extraBabelPlugins: ['babel-plugin-dynamic-import-node'],
|
|
25
36
|
|
|
@@ -29,6 +40,7 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
29
40
|
memo.optimization.splitChunks(false);
|
|
30
41
|
// 禁用 runtimeChunk
|
|
31
42
|
memo.optimization.runtimeChunk(false);
|
|
43
|
+
applySentryPlugin({ memo, appName: 'layout' });
|
|
32
44
|
return memo;
|
|
33
45
|
},
|
|
34
46
|
publicPath: PUBLIC_PATH,
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
### 核心实现
|
|
20
20
|
|
|
21
|
-
1.
|
|
22
|
-
2.
|
|
21
|
+
1. 主应用优先通过 `window.__MICO_PAGES__` 获取页面配置,无数据时降级到 `window.__MICO_MENUS__`(详见 [路由与菜单解耦](./feature-路由与菜单解耦.md))
|
|
22
|
+
2. 解析页面时根据 `htmlUrl` 或 `jsUrls` 判断是否为微应用
|
|
23
23
|
3. 路由匹配时,微应用类型使用 `MicroAppLoader` 组件加载
|
|
24
24
|
4. `MicroAppLoader` 使用 qiankun 的 `loadMicroApp` API 动态挂载子应用
|
|
25
25
|
5. 组件卸载时自动调用 `unmount()` 清理子应用
|
|
@@ -421,6 +421,8 @@ export default function HomePage() {
|
|
|
421
421
|
|
|
422
422
|
## 相关文档
|
|
423
423
|
|
|
424
|
+
- [路由与菜单解耦](./feature-路由与菜单解耦.md) - 路由注册与菜单导航数据源分离
|
|
425
|
+
- [菜单权限控制](./feature-菜单权限控制.md) - sideMenus 白名单权限逻辑
|
|
424
426
|
- [主题色切换](./feature-主题色切换.md) - 主题系统实现与子应用适配
|
|
425
427
|
- [请求模块架构](./arch-请求模块.md) - HTTP 请求层模块化设计
|
|
426
428
|
- [日志与常量](./arch-日志与常量.md) - Logger 工具与常量管理
|