generator-mico-cli 0.2.19 → 0.2.21

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.
Files changed (44) hide show
  1. package/README.md +29 -0
  2. package/bin/mico.js +124 -5
  3. package/generators/micro-react/index.js +86 -17
  4. package/generators/micro-react/templates/.eslintrc.js +24 -1
  5. package/generators/micro-react/templates/CICD/start_dev.sh +1 -1
  6. package/generators/micro-react/templates/CLAUDE.md +11 -5
  7. package/generators/micro-react/templates/_gitignore +2 -0
  8. package/generators/micro-react/templates/apps/layout/config/config.ts +21 -0
  9. package/generators/micro-react/templates/apps/layout/docs/common-intl.md +23 -21
  10. package/generators/micro-react/templates/apps/layout/docs/feature-/344/270/273/351/242/230/350/211/262/345/210/207/346/215/242.md +1 -1
  11. 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 +61 -36
  12. 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 +7 -2
  13. package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +4 -2
  14. package/generators/micro-react/templates/apps/layout/mock/menus.ts +7 -2
  15. package/generators/micro-react/templates/apps/layout/package.json +3 -2
  16. package/generators/micro-react/templates/apps/layout/src/common/locale.ts +3 -3
  17. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +3 -15
  18. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +4 -0
  19. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +1 -1
  20. package/generators/micro-react/templates/apps/layout/src/global.less +2 -3
  21. package/generators/micro-react/templates/apps/layout/src/services/config/type.ts +2 -4
  22. package/generators/micro-react/templates/package.json +5 -2
  23. package/generators/micro-react/templates/packages/common-intl/README.md +8 -8
  24. package/generators/micro-react/templates/packages/common-intl/src/intl.ts +13 -5678
  25. package/generators/micro-react/templates/packages/common-intl/src/utils.ts +22 -21
  26. package/generators/subapp-react/index.js +81 -13
  27. package/generators/subapp-react/templates/homepage/config/config.dev.ts +8 -1
  28. package/generators/subapp-react/templates/homepage/config/config.ts +21 -0
  29. package/generators/subapp-react/templates/homepage/config/routes.ts +1 -1
  30. package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
  31. package/generators/subapp-react/templates/homepage/package.json +3 -2
  32. package/generators/subapp-react/templates/homepage/src/app.tsx +1 -1
  33. package/generators/subapp-react/templates/homepage/src/common/request.ts +2 -2
  34. package/generators/subapp-react/templates/homepage/src/global.less +2 -1
  35. package/generators/subapp-react/templates/homepage/src/pages/index.less +1 -1
  36. package/generators/subapp-react/templates/homepage/src/pages/index.tsx +27 -27
  37. package/lib/utils.js +200 -2
  38. package/package.json +1 -1
  39. package/generators/micro-react/templates/packages/common-intl/.turbo/turbo-build.log +0 -13
  40. package/generators/micro-react/templates/packages/common-intl/dist/index.d.ts +0 -3
  41. package/generators/micro-react/templates/packages/common-intl/dist/index.js +0 -4388
  42. package/generators/micro-react/templates/packages/common-intl/dist/indexedDBUtils.d.ts +0 -13
  43. package/generators/micro-react/templates/packages/common-intl/dist/intl.d.ts +0 -1022
  44. package/generators/micro-react/templates/packages/common-intl/dist/utils.d.ts +0 -122
package/README.md CHANGED
@@ -48,12 +48,41 @@ mico list
48
48
  mico create micro-react --verbose
49
49
  ```
50
50
 
51
+ 预览模式(只显示将创建的文件,不实际创建):
52
+
53
+ ```bash
54
+ mico create micro-react --dry-run
55
+ ```
56
+
57
+ 检查环境依赖:
58
+
59
+ ```bash
60
+ mico doctor
61
+ ```
62
+
51
63
  将额外参数传递给生成器:
52
64
 
53
65
  ```bash
54
66
  mico create micro-react -- --help
55
67
  ```
56
68
 
69
+ ## 配置文件
70
+
71
+ 可以在项目目录或用户主目录创建 `.micorc` 或 `.micorc.json` 文件来预设默认值:
72
+
73
+ ```json
74
+ {
75
+ "packageScope": "@my-company",
76
+ "cdnPrefix": "portal",
77
+ "author": "Team <team@example.com>",
78
+ "defaultSubappName": "subapp"
79
+ }
80
+ ```
81
+
82
+ 配置查找顺序:
83
+ 1. 当前目录的 `.micorc` 或 `.micorc.json`
84
+ 2. 用户主目录的 `.micorc` 或 `.micorc.json`
85
+
57
86
  ## Monorepo 项目生成器 (micro-react)
58
87
 
59
88
  创建基于 qiankun 微前端架构的完整 Monorepo 项目:
package/bin/mico.js CHANGED
@@ -22,18 +22,32 @@ Commands:
22
22
  create <generator> Run a generator (e.g., mico create subapp-react)
23
23
  list List all available generators
24
24
  update Update mico-cli to the latest version
25
+ doctor Check environment dependencies
25
26
 
26
27
  Options:
27
28
  --help, -h Show this help message
28
29
  --version, -v Show version number
29
30
  --verbose Show detailed output during generation
31
+ --dry-run Preview files without creating them
30
32
  --no-update-check Skip update check
31
33
 
32
34
  Examples:
33
35
  mico create subapp-react
34
36
  mico create micro-react --verbose
37
+ mico create micro-react --dry-run
35
38
  mico list
36
39
  mico update
40
+ mico doctor
41
+
42
+ Configuration:
43
+ Create a .micorc or .micorc.json file in your project or home directory
44
+ to set default values for prompts:
45
+
46
+ {
47
+ "packageScope": "@my-company",
48
+ "cdnPrefix": "portal",
49
+ "author": "Team <team@example.com>"
50
+ }
37
51
 
38
52
  Notes:
39
53
  Requires Yeoman CLI (yo) installed globally.
@@ -118,6 +132,85 @@ function printVersion() {
118
132
  console.log(`mico-cli v${pkg.version}`);
119
133
  }
120
134
 
135
+ /**
136
+ * 运行 doctor 检查
137
+ */
138
+ async function runDoctor() {
139
+ const { runDoctorChecks, loadMicorc } = require('../lib/utils');
140
+
141
+ console.log('');
142
+ console.log(` \x1b[1mMico CLI Environment Check\x1b[0m (v${pkg.version})`);
143
+ console.log('');
144
+
145
+ const results = await runDoctorChecks();
146
+
147
+ // Node.js
148
+ const nodeIcon = results.node.satisfied ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
149
+ const nodeStatus = results.node.satisfied ? 'OK' : `Required: >= ${results.node.required}`;
150
+ console.log(` ${nodeIcon} Node.js ${results.node.current} (${nodeStatus})`);
151
+
152
+ // pnpm
153
+ const pnpmIcon = results.pnpm.available ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
154
+ if (results.pnpm.available) {
155
+ console.log(` ${pnpmIcon} pnpm ${results.pnpm.version}`);
156
+ } else {
157
+ console.log(` ${pnpmIcon} pnpm not found`);
158
+ console.log(' Install: npm install -g pnpm');
159
+ }
160
+
161
+ // Yeoman
162
+ const yoIcon = results.yo.available ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
163
+ if (results.yo.available) {
164
+ console.log(` ${yoIcon} yo ${results.yo.version}`);
165
+ } else {
166
+ console.log(` ${yoIcon} yo not found`);
167
+ console.log(' Install: npm install -g yo');
168
+ }
169
+
170
+ // Git
171
+ const gitIcon = results.git.available ? '\x1b[32m✓\x1b[0m' : '\x1b[33m⚠\x1b[0m';
172
+ if (results.git.available) {
173
+ console.log(` ${gitIcon} git ${results.git.version}`);
174
+ } else {
175
+ console.log(` ${gitIcon} git not found (optional)`);
176
+ }
177
+
178
+ // npm registry
179
+ const npmIcon = results.npm.reachable ? '\x1b[32m✓\x1b[0m' : '\x1b[33m⚠\x1b[0m';
180
+ if (results.npm.reachable) {
181
+ console.log(` ${npmIcon} npm registry reachable`);
182
+ } else {
183
+ console.log(` ${npmIcon} npm registry unreachable (${results.npm.error})`);
184
+ }
185
+
186
+ // .micorc 配置
187
+ console.log('');
188
+ const { config, configPath } = loadMicorc();
189
+ if (configPath) {
190
+ console.log(` \x1b[32m✓\x1b[0m Config loaded from: ${configPath}`);
191
+ const keys = Object.keys(config);
192
+ if (keys.length > 0) {
193
+ console.log(` Keys: ${keys.join(', ')}`);
194
+ }
195
+ } else {
196
+ console.log(' \x1b[2m○\x1b[0m No .micorc config found (optional)');
197
+ }
198
+
199
+ console.log('');
200
+
201
+ // 总结
202
+ const allGood = results.node.satisfied && results.pnpm.available && results.yo.available;
203
+ if (allGood) {
204
+ console.log(' \x1b[32m✅ All required dependencies are installed!\x1b[0m');
205
+ } else {
206
+ console.log(' \x1b[31m❌ Some required dependencies are missing.\x1b[0m');
207
+ console.log(' Please install them before using mico-cli.');
208
+ }
209
+ console.log('');
210
+
211
+ return allGood;
212
+ }
213
+
121
214
  /**
122
215
  * 检查是否有新版本
123
216
  * @returns {Promise<{current: string, latest: string, hasUpdate: boolean} | null>}
@@ -256,6 +349,7 @@ function performUpdate(latestVersion) {
256
349
  * @param {string[]} passthroughArgs - 透传参数
257
350
  * @param {object} options - 选项
258
351
  * @param {boolean} options.verbose - 是否启用详细输出
352
+ * @param {boolean} options.dryRun - 是否启用 dry-run 模式
259
353
  */
260
354
  function runGenerator(generator, rest, passthroughArgs, options = {}) {
261
355
  const localGeneratorEntry = path.join(
@@ -275,17 +369,31 @@ function runGenerator(generator, rest, passthroughArgs, options = {}) {
275
369
 
276
370
  const yoArgs = [yoGenerator, ...rest];
277
371
 
372
+ // 添加 dry-run 参数给 yeoman
373
+ if (options.dryRun) {
374
+ yoArgs.push('--dry-run');
375
+ }
376
+
278
377
  if (passthroughArgs.length > 0) {
279
378
  yoArgs.push('--', ...passthroughArgs);
280
379
  }
281
380
 
282
- // 通过环境变量传递 verbose 标志给生成器
381
+ // 通过环境变量传递标志给生成器
283
382
  const env = { ...process.env };
284
383
  if (options.verbose) {
285
384
  env.MICO_VERBOSE = '1';
385
+ }
386
+ if (options.dryRun) {
387
+ env.MICO_DRY_RUN = '1';
388
+ }
389
+
390
+ if (options.verbose) {
286
391
  console.log('');
287
392
  console.log(' \x1b[2m[verbose] Running generator:', yoGenerator, '\x1b[0m');
288
393
  console.log(' \x1b[2m[verbose] Arguments:', yoArgs.join(' '), '\x1b[0m');
394
+ if (options.dryRun) {
395
+ console.log(' \x1b[2m[verbose] Dry-run mode enabled\x1b[0m');
396
+ }
289
397
  console.log('');
290
398
  }
291
399
 
@@ -323,6 +431,7 @@ async function main() {
323
431
  const hasVersion = mainArgs.includes('--version') || mainArgs.includes('-v');
324
432
  const skipUpdateCheck = mainArgs.includes('--no-update-check');
325
433
  const isVerbose = mainArgs.includes('--verbose');
434
+ const isDryRun = mainArgs.includes('--dry-run');
326
435
 
327
436
  // 过滤掉标志参数
328
437
  const filteredArgs = mainArgs.filter(
@@ -332,7 +441,8 @@ async function main() {
332
441
  arg !== '--version' &&
333
442
  arg !== '-v' &&
334
443
  arg !== '--no-update-check' &&
335
- arg !== '--verbose'
444
+ arg !== '--verbose' &&
445
+ arg !== '--dry-run'
336
446
  );
337
447
 
338
448
  // 处理 --version
@@ -355,6 +465,12 @@ async function main() {
355
465
  process.exit(0);
356
466
  }
357
467
 
468
+ // 处理 doctor 命令
469
+ if (command === 'doctor') {
470
+ const success = await runDoctor();
471
+ process.exit(success ? 0 : 1);
472
+ }
473
+
358
474
  // 处理 update 命令
359
475
  if (command === 'update') {
360
476
  const updateInfo = await checkForUpdate();
@@ -376,8 +492,8 @@ async function main() {
376
492
  process.exit(1);
377
493
  }
378
494
 
379
- // 检查更新(除非跳过)
380
- if (!skipUpdateCheck) {
495
+ // 检查更新(除非跳过或 dry-run)
496
+ if (!skipUpdateCheck && !isDryRun) {
381
497
  const updateInfo = await checkForUpdate();
382
498
  if (updateInfo && updateInfo.hasUpdate) {
383
499
  const shouldUpdate = await askForUpdate(
@@ -396,7 +512,10 @@ async function main() {
396
512
  }
397
513
 
398
514
  // 运行生成器
399
- runGenerator(generator, rest.slice(1), passthroughArgs, { verbose: isVerbose });
515
+ runGenerator(generator, rest.slice(1), passthroughArgs, {
516
+ verbose: isVerbose,
517
+ dryRun: isDryRun
518
+ });
400
519
  return;
401
520
  }
402
521
 
@@ -9,10 +9,10 @@ const {
9
9
  collectFiles,
10
10
  transformDestPath,
11
11
  isTemplateFile,
12
- getLatestNpmVersion,
12
+ getPackageVersionsParallel,
13
13
  setupErrorHandlers,
14
14
  createLogger,
15
- // isVerbose,
15
+ loadMicorc,
16
16
  } = require('../../lib/utils');
17
17
 
18
18
  const IGNORE_LIST = require('./ignore-list.json');
@@ -25,6 +25,17 @@ module.exports = class extends Generator {
25
25
  this.projectRoot = process.cwd();
26
26
  this.logger = createLogger(this);
27
27
 
28
+ // 检查 dry-run 模式
29
+ this.isDryRun = this.options.dryRun || process.env.MICO_DRY_RUN === '1';
30
+
31
+ // 加载 .micorc 配置
32
+ const { config: rcConfig, configPath } = loadMicorc(this.projectRoot);
33
+ this.rcConfig = rcConfig;
34
+ if (configPath) {
35
+ this.logger.verbose('Loaded config from:', configPath);
36
+ this.logger.verbose('Config:', JSON.stringify(rcConfig, null, 2));
37
+ }
38
+
28
39
  // 检查当前目录是否已是一个 monorepo
29
40
  const workspaceFile = path.join(this.projectRoot, 'pnpm-workspace.yaml');
30
41
  if (fs.existsSync(workspaceFile)) {
@@ -46,12 +57,15 @@ module.exports = class extends Generator {
46
57
 
47
58
  async prompting() {
48
59
  try {
60
+ // 使用 .micorc 中的值作为默认值
61
+ const rc = this.rcConfig || {};
62
+
49
63
  this.answers = await this.prompt([
50
64
  {
51
65
  type: 'input',
52
66
  name: 'projectName',
53
67
  message: 'Project name',
54
- default: path.basename(this.projectRoot),
68
+ default: rc.projectName || path.basename(this.projectRoot),
55
69
  filter: (input) => toKebab(input),
56
70
  validate: (input) => {
57
71
  const value = toKebab(input);
@@ -63,7 +77,7 @@ module.exports = class extends Generator {
63
77
  type: 'input',
64
78
  name: 'packageScope',
65
79
  message: 'Package scope (e.g., @my-project)',
66
- default: (answers) => `@${toKebab(answers.projectName)}`,
80
+ default: (answers) => rc.packageScope || `@${toKebab(answers.projectName)}`,
67
81
  validate: (input) => {
68
82
  if (!input) return 'Package scope is required';
69
83
  if (!input.startsWith('@'))
@@ -80,7 +94,7 @@ module.exports = class extends Generator {
80
94
  - 输入 "portal": https://cdn.example.com/portal/my-project/1.0.0/
81
95
  - 输入 "admin/v2": https://cdn.example.com/admin/v2/my-project/1.0.0/
82
96
  Prefix`,
83
- default: '',
97
+ default: rc.cdnPrefix || '',
84
98
  filter: (input) => {
85
99
  // 移除首尾斜杠,规范化路径
86
100
  return input.trim().replace(/^\/+|\/+$/g, '');
@@ -90,7 +104,7 @@ module.exports = class extends Generator {
90
104
  type: 'input',
91
105
  name: 'author',
92
106
  message: 'Author',
93
- default: 'Your Name <email@example.com>',
107
+ default: rc.author || 'Your Name <email@example.com>',
94
108
  },
95
109
  ]);
96
110
 
@@ -110,7 +124,7 @@ module.exports = class extends Generator {
110
124
  }
111
125
  }
112
126
 
113
- writing() {
127
+ async writing() {
114
128
  try {
115
129
  if (!fs.existsSync(this.templateDir)) {
116
130
  console.error('');
@@ -125,21 +139,21 @@ module.exports = class extends Generator {
125
139
 
126
140
  // 在 mico_cli 根目录执行 npm view,以使用该目录 .npmrc 中的 Nexus 认证
127
141
  const cliRoot = path.resolve(__dirname, '../..');
128
- this.logger.verbose('Fetching latest package versions...');
142
+ this.logger.verbose('Fetching latest package versions (parallel)...');
129
143
 
130
- const micoUiVer = getLatestNpmVersion(
131
- '@mico-platform/ui',
132
- '1.0.0',
133
- 8000,
134
- cliRoot,
135
- );
136
- const themeVer = getLatestNpmVersion(
137
- '@mico-platform/theme',
138
- '1.0.0',
144
+ // 并行获取版本
145
+ const versions = await getPackageVersionsParallel(
146
+ [
147
+ { name: '@mico-platform/ui', fallback: '1.0.0' },
148
+ { name: '@mico-platform/theme', fallback: '1.0.0' },
149
+ ],
139
150
  8000,
140
151
  cliRoot,
141
152
  );
142
153
 
154
+ const micoUiVer = versions['@mico-platform/ui'];
155
+ const themeVer = versions['@mico-platform/theme'];
156
+
143
157
  this.logger.verbose('@mico-platform/ui version:', micoUiVer);
144
158
  this.logger.verbose('@mico-platform/theme version:', themeVer);
145
159
 
@@ -173,6 +187,45 @@ module.exports = class extends Generator {
173
187
  process.exit(1);
174
188
  }
175
189
 
190
+ // Dry-run 模式:只列出文件,不实际创建
191
+ if (this.isDryRun) {
192
+ this.log('');
193
+ this.log('\x1b[33m📋 Dry run mode - no files will be created\x1b[0m');
194
+ this.log('');
195
+ this.log(` Project: ${this.projectName}`);
196
+ this.log(` Scope: ${this.packageScope}`);
197
+ this.log(` Destination: ${this.destDir}`);
198
+ this.log('');
199
+ this.log(' Would create the following files:');
200
+ this.log('');
201
+
202
+ let templateCount = 0;
203
+ let copyCount = 0;
204
+
205
+ for (const relPath of files) {
206
+ const destRelPath = transformDestPath(relPath);
207
+ const isTemplate = isTemplateFile(relPath);
208
+ const tag = isTemplate ? '\x1b[32m[tpl]\x1b[0m' : '\x1b[36m[cpy]\x1b[0m';
209
+ this.log(` ${tag} ${destRelPath}`);
210
+
211
+ if (isTemplate) {
212
+ templateCount++;
213
+ } else {
214
+ copyCount++;
215
+ }
216
+ }
217
+
218
+ this.log('');
219
+ this.log(` Total: ${files.length} files (${templateCount} templates, ${copyCount} static)`);
220
+ this.log('');
221
+ this.log(' Run without --dry-run to actually create these files.');
222
+ this.log('');
223
+
224
+ // 设置标记以跳过后续阶段
225
+ this._skipInstall = true;
226
+ return;
227
+ }
228
+
176
229
  this.log('');
177
230
  this.log(`📦 Creating project: ${this.projectName}`);
178
231
  this.log(` Scope: ${this.packageScope}`);
@@ -210,6 +263,19 @@ module.exports = class extends Generator {
210
263
  }
211
264
 
212
265
  install() {
266
+ // 跳过 dry-run 模式
267
+ if (this._skipInstall) return;
268
+
269
+ // 检查并初始化 git
270
+ const gitDir = path.join(this.destDir, '.git');
271
+ if (!fs.existsSync(gitDir)) {
272
+ this.log('');
273
+ this.log('🔧 初始化 Git 仓库...');
274
+ this.spawnCommandSync('git', ['init'], {
275
+ cwd: this.destDir,
276
+ });
277
+ }
278
+
213
279
  this.log('');
214
280
  this.log('📦 正在安装依赖...');
215
281
  this.spawnCommandSync('pnpm', ['install'], {
@@ -218,6 +284,9 @@ module.exports = class extends Generator {
218
284
  }
219
285
 
220
286
  end() {
287
+ // 跳过 dry-run 模式
288
+ if (this._skipInstall) return;
289
+
221
290
  this.log('');
222
291
  this.log('✅ 项目创建成功!');
223
292
  this.log('');
@@ -19,7 +19,30 @@ module.exports = {
19
19
  },
20
20
  ],
21
21
  },
22
- // 忽略 apps/ 子包和 scripts/
22
+ // TypeScript 文件使用专门的 parser
23
+ overrides: [
24
+ {
25
+ files: ["*.ts", "*.tsx"],
26
+ parser: "@typescript-eslint/parser",
27
+ plugins: ["@typescript-eslint"],
28
+ extends: [
29
+ "eslint:recommended",
30
+ "plugin:@typescript-eslint/recommended",
31
+ ],
32
+ rules: {
33
+ // 使用 TS 版本的 no-unused-vars
34
+ "no-unused-vars": "off",
35
+ "@typescript-eslint/no-unused-vars": [
36
+ "warn",
37
+ {
38
+ argsIgnorePattern: "^_",
39
+ varsIgnorePattern: "^_",
40
+ },
41
+ ],
42
+ },
43
+ },
44
+ ],
45
+ // 忽略 apps/ 子包和 scripts/,apps由内部的eslint规则处理
23
46
  ignorePatterns: [
24
47
  'node_modules/',
25
48
  'dist/',
@@ -38,7 +38,7 @@ pnpm run build:development
38
38
 
39
39
  # 只有在 CI 环境时才写入版本号文件(覆盖写入)
40
40
  if [ "${CI}" = "true" ]; then
41
- echo "VERSION=$VERSION" > .env_x_<%= projectName %>portal-web
41
+ echo "VERSION=$VERSION" > .env_x_<%= projectName %>
42
42
  fi
43
43
 
44
44
 
@@ -53,15 +53,21 @@ apps/ # Workspace 应用目录(微前端子应用)
53
53
  │ │ ├── app.tsx # Umi 运行时配置
54
54
  │ │ ├── layouts/ # 布局组件
55
55
  │ │ ├── pages/ # 路由页面
56
- │ │ ├── components/ # 公共组件
56
+ │ │ ├── components/ # 公共组件(MicroAppLoader 等)
57
57
  │ │ ├── common/ # 工具模块(auth、request、upload、menu)
58
+ │ │ ├── constants/ # 常量定义(路由、主题、时区等)
58
59
  │ │ ├── hooks/ # 自定义 Hooks
59
60
  │ │ ├── services/ # API 服务层
60
61
  │ │ ├── models/ # Umi model(全局状态)
61
- │ │ ├── locales/ # 国际化文件(zh-CN、en-US)
62
- │ │ └── styles/ # 主题变量与样式覆盖
62
+ │ │ └── locales/ # 国际化文件(zh-CN、en-US)
63
63
  │ └── config/ # Umi 配置
64
- packages/ # 共享包
64
+ ├── basis/ # 基础数据子应用(货币管理等)
65
+ │ ├── src/
66
+ │ │ ├── pages/ # 路由页面
67
+ │ │ ├── locales/ # 国际化文件
68
+ │ │ └── common/ # 工具模块
69
+ │ └── config/ # Umi 配置
70
+ packages/ # 共享包(common-intl 等)
65
71
  scripts/ # 构建与开发脚本
66
72
  CICD/ # 部署资源
67
73
  ```
@@ -97,7 +103,7 @@ refactor(auth): 重构认证服务
97
103
  API 请求配置在 `src/common/request/`(模块化拆分为 6 个文件),错误处理在 `src/requestErrorConfig.ts`。详见 [请求模块架构](./apps/layout/docs/arch-请求模块.md)。
98
104
 
99
105
  ### 日志与常量
100
- Logger 工具在 `src/common/logger.ts`,常量定义在 `src/common/constants.ts`。详见 [日志与常量](./apps/layout/docs/arch-日志与常量.md)。
106
+ Logger 工具在 `src/common/logger.ts`,常量定义在 `src/constants/index.ts`。详见 [日志与常量](./apps/layout/docs/arch-日志与常量.md)。
101
107
 
102
108
  ### 认证模块
103
109
  认证逻辑在 `src/common/auth/`,核心文件 `auth-manager.ts` 管理 Token 存储和用户信息。SSO 登录在 `getInitialState()` 中完成,确保 UI 渲染前认证已就绪。
@@ -55,3 +55,5 @@ build
55
55
  /openspec
56
56
 
57
57
  **/tasks/*
58
+
59
+ .pnpm-store/**
@@ -118,6 +118,27 @@ const config: ReturnType<typeof defineConfig> = {
118
118
  */
119
119
  tailwindcss: {},
120
120
 
121
+ /**
122
+ * @name 额外 Babel Presets
123
+ * @description 使用 @mico-platform/ui 的 babel preset,实现组件与图标的按需加载
124
+ */
125
+ extraBabelPresets: ['@mico-platform/ui/babel-preset'],
126
+
127
+ /**
128
+ * @name MFSU 配置
129
+ * @description
130
+ * - exclude: theme 子路径解析;ui 尽量与主应用一起编译
131
+ * - shared: React 单例,确保 MFSU 预打包里的组件(如 Layout)与主应用共用同一份 React,否则 useContext 报 null
132
+ * @doc https://umijs.org/docs/guides/mfsu
133
+ */
134
+ mfsu: {
135
+ exclude: ['@mico-platform/theme', '@mico-platform/ui'],
136
+ shared: {
137
+ react: { singleton: true },
138
+ 'react-dom': { singleton: true },
139
+ },
140
+ },
141
+
121
142
  /**
122
143
  * @name qiankun 微前端配置
123
144
  * @description 作为主应用,动态加载子应用