generator-mico-cli 0.2.16 → 0.2.18
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 +12 -0
- package/bin/mico.js +101 -5
- package/generators/micro-react/index.js +46 -0
- package/generators/micro-react/meta.json +12 -0
- package/generators/micro-react/templates/.cursor/rules/cicd-deploy.mdc +10 -8
- package/generators/micro-react/templates/.cursor/rules/development-guide.mdc +1 -1
- package/generators/micro-react/templates/AGENTS.md +3 -0
- package/generators/micro-react/templates/CICD/start_dev.sh +2 -1
- package/generators/micro-react/templates/CICD/start_prod.sh +2 -1
- package/generators/micro-react/templates/CICD/start_test.sh +2 -1
- package/generators/micro-react/templates/CICD/wangsu_fresh_dev.sh +4 -4
- package/generators/micro-react/templates/CICD/wangsu_fresh_prod.sh +4 -4
- package/generators/micro-react/templates/CICD/wangsu_fresh_test.sh +4 -4
- package/generators/micro-react/templates/README.md +39 -1
- package/generators/micro-react/templates/apps/layout/config/config.dev.ts +1 -1
- package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +1 -1
- package/generators/micro-react/templates/apps/layout/config/config.prod.ts +3 -3
- package/generators/micro-react/templates/apps/layout/config/config.ts +1 -1
- 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
- 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 -4
- package/generators/micro-react/templates/apps/layout/src/app.tsx +2 -2
- package/generators/micro-react/templates/apps/layout/src/components/HeaderDropdown/index.tsx +0 -2
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +3 -0
- package/generators/micro-react/templates/apps/layout/src/layouts/index.less +2 -1
- package/generators/micro-react/templates/deployDesc.md +3 -3
- package/generators/micro-react/templates/dev.preset.json +14 -0
- package/generators/micro-react/templates/docs/dev-preset.md +130 -0
- package/generators/micro-react/templates/package.json +2 -0
- package/generators/micro-react/templates/scripts/dev-preset.js +265 -0
- package/generators/micro-react/templates/scripts/dev-preset.schema.json +39 -0
- package/generators/subapp-react/index.js +31 -1
- package/generators/subapp-react/meta.json +10 -0
- package/generators/subapp-react/templates/homepage/config/config.dev.ts +2 -3
- package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +1 -1
- package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +1 -1
- package/generators/subapp-react/templates/homepage/config/config.prod.ts +1 -1
- package/generators/subapp-react/templates/homepage/src/pages/index.tsx +1 -1
- package/lib/utils.js +49 -1
- package/package.json +3 -2
package/README.md
CHANGED
package/bin/mico.js
CHANGED
|
@@ -20,16 +20,19 @@ Usage: mico <command> [options]
|
|
|
20
20
|
|
|
21
21
|
Commands:
|
|
22
22
|
create <generator> Run a generator (e.g., mico create subapp-react)
|
|
23
|
+
list List all available generators
|
|
23
24
|
update Update mico-cli to the latest version
|
|
24
25
|
|
|
25
26
|
Options:
|
|
26
27
|
--help, -h Show this help message
|
|
27
28
|
--version, -v Show version number
|
|
29
|
+
--verbose Show detailed output during generation
|
|
28
30
|
--no-update-check Skip update check
|
|
29
31
|
|
|
30
32
|
Examples:
|
|
31
33
|
mico create subapp-react
|
|
32
|
-
mico create
|
|
34
|
+
mico create micro-react --verbose
|
|
35
|
+
mico list
|
|
33
36
|
mico update
|
|
34
37
|
|
|
35
38
|
Notes:
|
|
@@ -38,6 +41,76 @@ Notes:
|
|
|
38
41
|
`);
|
|
39
42
|
}
|
|
40
43
|
|
|
44
|
+
/**
|
|
45
|
+
* 列出所有可用的生成器
|
|
46
|
+
*/
|
|
47
|
+
function listGenerators() {
|
|
48
|
+
const generatorsDir = path.join(rootDir, 'generators');
|
|
49
|
+
|
|
50
|
+
if (!fs.existsSync(generatorsDir)) {
|
|
51
|
+
console.error('❌ Error: generators directory not found.');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const entries = fs.readdirSync(generatorsDir, { withFileTypes: true });
|
|
56
|
+
const generators = [];
|
|
57
|
+
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
if (!entry.isDirectory()) continue;
|
|
60
|
+
|
|
61
|
+
const generatorPath = path.join(generatorsDir, entry.name);
|
|
62
|
+
const indexPath = path.join(generatorPath, 'index.js');
|
|
63
|
+
const metaPath = path.join(generatorPath, 'meta.json');
|
|
64
|
+
|
|
65
|
+
// 必须有 index.js 才算有效生成器
|
|
66
|
+
if (!fs.existsSync(indexPath)) continue;
|
|
67
|
+
|
|
68
|
+
let meta = { name: entry.name, description: '(No description)' };
|
|
69
|
+
if (fs.existsSync(metaPath)) {
|
|
70
|
+
try {
|
|
71
|
+
meta = { ...meta, ...JSON.parse(fs.readFileSync(metaPath, 'utf8')) };
|
|
72
|
+
} catch {
|
|
73
|
+
// 忽略解析错误
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
generators.push(meta);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (generators.length === 0) {
|
|
81
|
+
console.log('');
|
|
82
|
+
console.log(' No generators found.');
|
|
83
|
+
console.log('');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log(` \x1b[1mAvailable Generators\x1b[0m (mico-cli v${pkg.version})`);
|
|
89
|
+
console.log('');
|
|
90
|
+
|
|
91
|
+
// 计算最长名称用于对齐
|
|
92
|
+
const maxNameLen = Math.max(...generators.map((g) => g.name.length));
|
|
93
|
+
|
|
94
|
+
for (const gen of generators) {
|
|
95
|
+
const name = gen.name.padEnd(maxNameLen + 2);
|
|
96
|
+
console.log(` \x1b[36m${name}\x1b[0m ${gen.description}`);
|
|
97
|
+
|
|
98
|
+
// 如果有 features,显示特性列表
|
|
99
|
+
if (gen.features && gen.features.length > 0) {
|
|
100
|
+
for (const feature of gen.features) {
|
|
101
|
+
console.log(` ${' '.repeat(maxNameLen + 2)} • ${feature}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 如果有 usage,显示用法
|
|
106
|
+
if (gen.usage) {
|
|
107
|
+
console.log(` ${' '.repeat(maxNameLen + 2)} \x1b[2m$ ${gen.usage}\x1b[0m`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log('');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
41
114
|
/**
|
|
42
115
|
* 打印版本信息
|
|
43
116
|
*/
|
|
@@ -178,8 +251,13 @@ function performUpdate(latestVersion) {
|
|
|
178
251
|
|
|
179
252
|
/**
|
|
180
253
|
* 运行 Yeoman 生成器
|
|
254
|
+
* @param {string} generator - 生成器名称
|
|
255
|
+
* @param {string[]} rest - 剩余参数
|
|
256
|
+
* @param {string[]} passthroughArgs - 透传参数
|
|
257
|
+
* @param {object} options - 选项
|
|
258
|
+
* @param {boolean} options.verbose - 是否启用详细输出
|
|
181
259
|
*/
|
|
182
|
-
function runGenerator(generator, rest, passthroughArgs) {
|
|
260
|
+
function runGenerator(generator, rest, passthroughArgs, options = {}) {
|
|
183
261
|
const localGeneratorEntry = path.join(
|
|
184
262
|
rootDir,
|
|
185
263
|
'generators',
|
|
@@ -201,7 +279,17 @@ function runGenerator(generator, rest, passthroughArgs) {
|
|
|
201
279
|
yoArgs.push('--', ...passthroughArgs);
|
|
202
280
|
}
|
|
203
281
|
|
|
204
|
-
|
|
282
|
+
// 通过环境变量传递 verbose 标志给生成器
|
|
283
|
+
const env = { ...process.env };
|
|
284
|
+
if (options.verbose) {
|
|
285
|
+
env.MICO_VERBOSE = '1';
|
|
286
|
+
console.log('');
|
|
287
|
+
console.log(' \x1b[2m[verbose] Running generator:', yoGenerator, '\x1b[0m');
|
|
288
|
+
console.log(' \x1b[2m[verbose] Arguments:', yoArgs.join(' '), '\x1b[0m');
|
|
289
|
+
console.log('');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const child = spawn('yo', yoArgs, { stdio: 'inherit', env });
|
|
205
293
|
|
|
206
294
|
child.on('error', (error) => {
|
|
207
295
|
if (error && error.code === 'ENOENT') {
|
|
@@ -234,6 +322,7 @@ async function main() {
|
|
|
234
322
|
const hasHelp = mainArgs.includes('--help') || mainArgs.includes('-h');
|
|
235
323
|
const hasVersion = mainArgs.includes('--version') || mainArgs.includes('-v');
|
|
236
324
|
const skipUpdateCheck = mainArgs.includes('--no-update-check');
|
|
325
|
+
const isVerbose = mainArgs.includes('--verbose');
|
|
237
326
|
|
|
238
327
|
// 过滤掉标志参数
|
|
239
328
|
const filteredArgs = mainArgs.filter(
|
|
@@ -242,7 +331,8 @@ async function main() {
|
|
|
242
331
|
arg !== '-h' &&
|
|
243
332
|
arg !== '--version' &&
|
|
244
333
|
arg !== '-v' &&
|
|
245
|
-
arg !== '--no-update-check'
|
|
334
|
+
arg !== '--no-update-check' &&
|
|
335
|
+
arg !== '--verbose'
|
|
246
336
|
);
|
|
247
337
|
|
|
248
338
|
// 处理 --version
|
|
@@ -259,6 +349,12 @@ async function main() {
|
|
|
259
349
|
|
|
260
350
|
const [command, ...rest] = filteredArgs;
|
|
261
351
|
|
|
352
|
+
// 处理 list 命令
|
|
353
|
+
if (command === 'list' || command === 'ls') {
|
|
354
|
+
listGenerators();
|
|
355
|
+
process.exit(0);
|
|
356
|
+
}
|
|
357
|
+
|
|
262
358
|
// 处理 update 命令
|
|
263
359
|
if (command === 'update') {
|
|
264
360
|
const updateInfo = await checkForUpdate();
|
|
@@ -300,7 +396,7 @@ async function main() {
|
|
|
300
396
|
}
|
|
301
397
|
|
|
302
398
|
// 运行生成器
|
|
303
|
-
runGenerator(generator, rest.slice(1), passthroughArgs);
|
|
399
|
+
runGenerator(generator, rest.slice(1), passthroughArgs, { verbose: isVerbose });
|
|
304
400
|
return;
|
|
305
401
|
}
|
|
306
402
|
|
|
@@ -11,6 +11,8 @@ const {
|
|
|
11
11
|
isTemplateFile,
|
|
12
12
|
getLatestNpmVersion,
|
|
13
13
|
setupErrorHandlers,
|
|
14
|
+
createLogger,
|
|
15
|
+
// isVerbose,
|
|
14
16
|
} = require('../../lib/utils');
|
|
15
17
|
|
|
16
18
|
const IGNORE_LIST = require('./ignore-list.json');
|
|
@@ -21,6 +23,7 @@ setupErrorHandlers();
|
|
|
21
23
|
module.exports = class extends Generator {
|
|
22
24
|
initializing() {
|
|
23
25
|
this.projectRoot = process.cwd();
|
|
26
|
+
this.logger = createLogger(this);
|
|
24
27
|
|
|
25
28
|
// 检查当前目录是否已是一个 monorepo
|
|
26
29
|
const workspaceFile = path.join(this.projectRoot, 'pnpm-workspace.yaml');
|
|
@@ -68,6 +71,21 @@ module.exports = class extends Generator {
|
|
|
68
71
|
return true;
|
|
69
72
|
},
|
|
70
73
|
},
|
|
74
|
+
{
|
|
75
|
+
type: 'input',
|
|
76
|
+
name: 'cdnPrefix',
|
|
77
|
+
message: `CDN path prefix (用于区分不同业务线的 CDN 目录)
|
|
78
|
+
示例:CDN 完整路径 = https://cdn.example.com/<prefix>/<projectName>/<version>/
|
|
79
|
+
- 留空: https://cdn.example.com/my-project/1.0.0/
|
|
80
|
+
- 输入 "portal": https://cdn.example.com/portal/my-project/1.0.0/
|
|
81
|
+
- 输入 "admin/v2": https://cdn.example.com/admin/v2/my-project/1.0.0/
|
|
82
|
+
Prefix`,
|
|
83
|
+
default: '',
|
|
84
|
+
filter: (input) => {
|
|
85
|
+
// 移除首尾斜杠,规范化路径
|
|
86
|
+
return input.trim().replace(/^\/+|\/+$/g, '');
|
|
87
|
+
},
|
|
88
|
+
},
|
|
71
89
|
{
|
|
72
90
|
type: 'input',
|
|
73
91
|
name: 'author',
|
|
@@ -79,6 +97,7 @@ module.exports = class extends Generator {
|
|
|
79
97
|
this.projectName = toKebab(this.answers.projectName);
|
|
80
98
|
this.ProjectName = toPascal(this.projectName);
|
|
81
99
|
this.packageScope = this.answers.packageScope;
|
|
100
|
+
this.cdnPrefix = this.answers.cdnPrefix;
|
|
82
101
|
this.author = this.answers.author;
|
|
83
102
|
this.templateDir = this.templatePath();
|
|
84
103
|
this.destDir = this.projectRoot;
|
|
@@ -101,8 +120,13 @@ module.exports = class extends Generator {
|
|
|
101
120
|
process.exit(1);
|
|
102
121
|
}
|
|
103
122
|
|
|
123
|
+
this.logger.verbose('Template directory:', this.templateDir);
|
|
124
|
+
this.logger.verbose('Destination directory:', this.destDir);
|
|
125
|
+
|
|
104
126
|
// 在 mico_cli 根目录执行 npm view,以使用该目录 .npmrc 中的 Nexus 认证
|
|
105
127
|
const cliRoot = path.resolve(__dirname, '../..');
|
|
128
|
+
this.logger.verbose('Fetching latest package versions...');
|
|
129
|
+
|
|
106
130
|
const micoUiVer = getLatestNpmVersion(
|
|
107
131
|
'@mico-platform/ui',
|
|
108
132
|
'1.0.0',
|
|
@@ -115,6 +139,13 @@ module.exports = class extends Generator {
|
|
|
115
139
|
8000,
|
|
116
140
|
cliRoot,
|
|
117
141
|
);
|
|
142
|
+
|
|
143
|
+
this.logger.verbose('@mico-platform/ui version:', micoUiVer);
|
|
144
|
+
this.logger.verbose('@mico-platform/theme version:', themeVer);
|
|
145
|
+
|
|
146
|
+
// 构建 CDN 路径片段:如果有 prefix 则加上斜杠前缀,否则为空
|
|
147
|
+
const cdnPrefixPath = this.cdnPrefix ? `${this.cdnPrefix}/` : '';
|
|
148
|
+
|
|
118
149
|
const templateData = {
|
|
119
150
|
projectName: this.projectName,
|
|
120
151
|
ProjectName: this.ProjectName,
|
|
@@ -122,8 +153,12 @@ module.exports = class extends Generator {
|
|
|
122
153
|
author: this.author,
|
|
123
154
|
micoUiVersion: `^${micoUiVer}`,
|
|
124
155
|
themeVersion: `^${themeVer}`,
|
|
156
|
+
cdnPrefix: this.cdnPrefix,
|
|
157
|
+
cdnPrefixPath, // 用于拼接路径,已包含尾部斜杠
|
|
125
158
|
};
|
|
126
159
|
|
|
160
|
+
this.logger.verbose('Template data:', JSON.stringify(templateData, null, 2));
|
|
161
|
+
|
|
127
162
|
const files = collectFiles(
|
|
128
163
|
this.templateDir,
|
|
129
164
|
this.templateDir,
|
|
@@ -143,17 +178,28 @@ module.exports = class extends Generator {
|
|
|
143
178
|
this.log(` Scope: ${this.packageScope}`);
|
|
144
179
|
this.log('');
|
|
145
180
|
|
|
181
|
+
this.logger.verbose(`Processing ${files.length} files...`);
|
|
182
|
+
|
|
183
|
+
let templateCount = 0;
|
|
184
|
+
let copyCount = 0;
|
|
185
|
+
|
|
146
186
|
for (const relPath of files) {
|
|
147
187
|
const srcPath = path.join(this.templateDir, relPath);
|
|
148
188
|
const destRelPath = transformDestPath(relPath);
|
|
149
189
|
const destPath = path.join(this.destDir, destRelPath);
|
|
150
190
|
|
|
151
191
|
if (isTemplateFile(relPath)) {
|
|
192
|
+
this.logger.file('template', destRelPath);
|
|
152
193
|
this.fs.copyTpl(srcPath, destPath, templateData);
|
|
194
|
+
templateCount++;
|
|
153
195
|
} else {
|
|
196
|
+
this.logger.file('copy', destRelPath);
|
|
154
197
|
this.fs.copy(srcPath, destPath);
|
|
198
|
+
copyCount++;
|
|
155
199
|
}
|
|
156
200
|
}
|
|
201
|
+
|
|
202
|
+
this.logger.verbose(`Processed: ${templateCount} templates, ${copyCount} copied`);
|
|
157
203
|
} catch (error) {
|
|
158
204
|
console.error('');
|
|
159
205
|
console.error('❌ Error during file generation:');
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "micro-react",
|
|
3
|
+
"description": "创建基于 qiankun 的微前端 Monorepo 项目",
|
|
4
|
+
"usage": "mkdir my-project && cd my-project && mico create micro-react",
|
|
5
|
+
"features": [
|
|
6
|
+
"Turborepo + pnpm Workspace",
|
|
7
|
+
"qiankun 微前端架构",
|
|
8
|
+
"Arco Design + Tailwind CSS",
|
|
9
|
+
"主题切换、国际化、认证模块",
|
|
10
|
+
"可配置 CDN 路径前缀(支持多业务线隔离)"
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -21,7 +21,7 @@ globs: ["CICD/**", "deployDesc.md"]
|
|
|
21
21
|
│ ↓ │
|
|
22
22
|
│ ┌─────────────────────────────────────────────────────────────┐│
|
|
23
23
|
│ │ 构建产物:dist/{app}/ ││
|
|
24
|
-
│ │ 上传 CDN:cdn-portal[-env].micoplatform.com/<%= projectName %>/ ││
|
|
24
|
+
│ │ 上传 CDN:cdn-portal[-env].micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/ ││
|
|
25
25
|
│ └─────────────────────────────────────────────────────────────┘│
|
|
26
26
|
└─────────────────────────────────────────────────────────────────┘
|
|
27
27
|
```
|
|
@@ -51,7 +51,7 @@ pnpm install
|
|
|
51
51
|
VERSION=$(node -p "require('./package.json').version")
|
|
52
52
|
|
|
53
53
|
# 3. 设置 CDN 路径
|
|
54
|
-
export CDN_PUBLIC_PATH="https://cdn-portal[-env].micoplatform.com/<%= projectName %>/${VERSION}/"
|
|
54
|
+
export CDN_PUBLIC_PATH="https://cdn-portal[-env].micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/${VERSION}/"
|
|
55
55
|
|
|
56
56
|
# 4. 执行构建
|
|
57
57
|
pnpm run build:[environment]
|
|
@@ -78,12 +78,14 @@ echo "VERSION=$VERSION" > .env_x_<%= projectName %>
|
|
|
78
78
|
### CDN 路径结构
|
|
79
79
|
```
|
|
80
80
|
cdn-portal.micoplatform.com/
|
|
81
|
-
|
|
82
|
-
└──
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
<% if (cdnPrefix) { %>└── <%= cdnPrefix %>/
|
|
82
|
+
└── <%= projectName %>/
|
|
83
|
+
<% } else { %>└── <%= projectName %>/
|
|
84
|
+
<% } %> └── {version}/
|
|
85
|
+
└── dist/
|
|
86
|
+
├── layout/ # 主应用
|
|
87
|
+
├── homepage/ # 子应用
|
|
88
|
+
└── ...
|
|
87
89
|
```
|
|
88
90
|
|
|
89
91
|
## 环境变量
|
|
@@ -273,7 +273,7 @@ sh CICD/start_prod.sh
|
|
|
273
273
|
|
|
274
274
|
构建产物上传到 CDN:
|
|
275
275
|
```
|
|
276
|
-
cdn-portal[-env].micoplatform.com/<%= projectName %>/{version}/dist/{app}/
|
|
276
|
+
cdn-portal[-env].micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/{version}/dist/{app}/
|
|
277
277
|
```
|
|
278
278
|
|
|
279
279
|
- `version`:`package.json` 的 version 字段
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
|
|
23
23
|
- `pnpm install` 安装 workspace 依赖。
|
|
24
24
|
- `pnpm dev` 运行交互式开发启动器(选择应用)。
|
|
25
|
+
- `pnpm dev:preset` 根据 `dev.preset.json` 配置,一次性并行启动多个应用。
|
|
26
|
+
- `pnpm dev:preset <preset>` 使用指定预设启动多应用。
|
|
27
|
+
- `pnpm list:preset` 列出所有可用的启动预设。
|
|
25
28
|
- `pnpm -C apps/<app> dev` 直接运行指定应用。
|
|
26
29
|
- `pnpm build` 构建所有应用用于生产环境;`pnpm build:development|testing|production|local` 设置不同环境模式。
|
|
27
30
|
- `pnpm lint` 运行 ESLint + Turbo lint 检查;`pnpm lint:fix` 自动修复。
|
|
@@ -30,7 +30,8 @@ if [ -f "$PROJECT_ROOT/CICD/before_build.sh" ]; then
|
|
|
30
30
|
fi
|
|
31
31
|
|
|
32
32
|
# 设置子应用的 CDN 公共路径(开发环境)
|
|
33
|
-
|
|
33
|
+
# 路径格式: https://cdn-xxx.com/<prefix>/<projectName>/<version>/
|
|
34
|
+
export CDN_PUBLIC_PATH="https://cdn-portal-dev.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/${VERSION}/"
|
|
34
35
|
echo "CDN_PUBLIC_PATH: $CDN_PUBLIC_PATH"
|
|
35
36
|
|
|
36
37
|
pnpm run build:development
|
|
@@ -30,7 +30,8 @@ if [ -f "$PROJECT_ROOT/CICD/before_build.sh" ]; then
|
|
|
30
30
|
fi
|
|
31
31
|
|
|
32
32
|
# 设置子应用的 CDN 公共路径(生产环境)
|
|
33
|
-
|
|
33
|
+
# 路径格式: https://cdn-xxx.com/<prefix>/<projectName>/<version>/
|
|
34
|
+
export CDN_PUBLIC_PATH="https://cdn-portal.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/${VERSION}/"
|
|
34
35
|
echo "CDN_PUBLIC_PATH: $CDN_PUBLIC_PATH"
|
|
35
36
|
|
|
36
37
|
pnpm run build:production
|
|
@@ -31,7 +31,8 @@ fi
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
# 设置子应用的 CDN 公共路径(测试环境)
|
|
34
|
-
|
|
34
|
+
# 路径格式: https://cdn-xxx.com/<prefix>/<projectName>/<version>/
|
|
35
|
+
export CDN_PUBLIC_PATH="https://cdn-portal-test.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/${VERSION}/"
|
|
35
36
|
echo "CDN_PUBLIC_PATH: $CDN_PUBLIC_PATH"
|
|
36
37
|
|
|
37
38
|
pnpm run build:testing
|
|
@@ -5,13 +5,13 @@ apiKey=$(cat ~/.wangsu_key)
|
|
|
5
5
|
date=`env LANG="en_US.UTF-8" date -u "+%a, %d %b %Y %H:%M:%S GMT"`
|
|
6
6
|
password=`echo -en "$date" | openssl dgst -sha1 -hmac $apiKey -binary | openssl enc -base64`
|
|
7
7
|
echo "打印刷新地址"
|
|
8
|
-
echo "dir1:http://cdn-portal-dev.micoplatform.com/<%= projectName %>/$version/"
|
|
9
|
-
echo "dir2:https://cdn-portal-dev.micoplatform.com/<%= projectName %>/$version/"
|
|
8
|
+
echo "dir1:http://cdn-portal-dev.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version/"
|
|
9
|
+
echo "dir2:https://cdn-portal-dev.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version/"
|
|
10
10
|
curl -i --url "https://open.chinanetcenter.com/ccm/purge/ItemIdReceiver" -X "POST" -u "$username:$password" -H "Date:$date" -H "Content-Type: application/json" --data-binary @- <<EOF
|
|
11
11
|
{
|
|
12
12
|
"dirs": [
|
|
13
|
-
"http://cdn-portal-dev.micoplatform.com/<%= projectName %>/$version",
|
|
14
|
-
"https://cdn-portal-dev.micoplatform.com/<%= projectName %>/$version"
|
|
13
|
+
"http://cdn-portal-dev.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version",
|
|
14
|
+
"https://cdn-portal-dev.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version"
|
|
15
15
|
],
|
|
16
16
|
"dirAction":"expire"
|
|
17
17
|
}
|
|
@@ -5,13 +5,13 @@ apiKey=$(cat ~/.wangsu_key)
|
|
|
5
5
|
date=`env LANG="en_US.UTF-8" date -u "+%a, %d %b %Y %H:%M:%S GMT"`
|
|
6
6
|
password=`echo -en "$date" | openssl dgst -sha1 -hmac $apiKey -binary | openssl enc -base64`
|
|
7
7
|
echo "打印刷新地址"
|
|
8
|
-
echo "dir1:http://cdn-portal.micoplatform.com/<%= projectName %>/$version/"
|
|
9
|
-
echo "dir2:https://cdn-portal.micoplatform.com/<%= projectName %>/$version/"
|
|
8
|
+
echo "dir1:http://cdn-portal.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version/"
|
|
9
|
+
echo "dir2:https://cdn-portal.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version/"
|
|
10
10
|
curl -i --url "https://open.chinanetcenter.com/ccm/purge/ItemIdReceiver" -X "POST" -u "$username:$password" -H "Date:$date" -H "Content-Type: application/json" --data-binary @- <<EOF
|
|
11
11
|
{
|
|
12
12
|
"dirs": [
|
|
13
|
-
"http://cdn-portal.micoplatform.com/<%= projectName %>/$version",
|
|
14
|
-
"https://cdn-portal.micoplatform.com/<%= projectName %>/$version"
|
|
13
|
+
"http://cdn-portal.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version",
|
|
14
|
+
"https://cdn-portal.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version"
|
|
15
15
|
],
|
|
16
16
|
"dirAction":"expire"
|
|
17
17
|
}
|
|
@@ -5,13 +5,13 @@ apiKey=$(cat ~/.wangsu_key)
|
|
|
5
5
|
date=`env LANG="en_US.UTF-8" date -u "+%a, %d %b %Y %H:%M:%S GMT"`
|
|
6
6
|
password=`echo -en "$date" | openssl dgst -sha1 -hmac $apiKey -binary | openssl enc -base64`
|
|
7
7
|
echo "打印刷新地址"
|
|
8
|
-
echo "dir1:http://cdn-portal-test.micoplatform.com/<%= projectName %>/$version/"
|
|
9
|
-
echo "dir2:https://cdn-portal-test.micoplatform.com/<%= projectName %>/$version/"
|
|
8
|
+
echo "dir1:http://cdn-portal-test.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version/"
|
|
9
|
+
echo "dir2:https://cdn-portal-test.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version/"
|
|
10
10
|
curl -i --url "https://open.chinanetcenter.com/ccm/purge/ItemIdReceiver" -X "POST" -u "$username:$password" -H "Date:$date" -H "Content-Type: application/json" --data-binary @- <<EOF
|
|
11
11
|
{
|
|
12
12
|
"dirs": [
|
|
13
|
-
"http://cdn-portal-test.micoplatform.com/<%= projectName %>/$version",
|
|
14
|
-
"https://cdn-portal-test.micoplatform.com/<%= projectName %>/$version"
|
|
13
|
+
"http://cdn-portal-test.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version",
|
|
14
|
+
"https://cdn-portal-test.micoplatform.com/<%= cdnPrefixPath %><%= projectName %>/$version"
|
|
15
15
|
],
|
|
16
16
|
"dirAction":"expire"
|
|
17
17
|
}
|
|
@@ -27,6 +27,9 @@ pnpm install
|
|
|
27
27
|
| 命令 | 说明 |
|
|
28
28
|
|------|------|
|
|
29
29
|
| `pnpm dev` | 交互式选择并启动应用开发服务器 |
|
|
30
|
+
| `pnpm dev:preset` | 根据配置文件并行启动多个应用 |
|
|
31
|
+
| `pnpm dev:preset <preset>` | 使用指定预设启动(如 `pnpm dev:preset full`) |
|
|
32
|
+
| `pnpm list:preset` | 列出所有可用的启动预设 |
|
|
30
33
|
| `pnpm build` | 构建所有应用(生产环境) |
|
|
31
34
|
| `pnpm build:development` | 构建所有应用(开发环境) |
|
|
32
35
|
| `pnpm build:testing` | 构建所有应用(测试环境) |
|
|
@@ -37,6 +40,39 @@ pnpm install
|
|
|
37
40
|
|
|
38
41
|
> **提示**:也可以使用 `pnpm -C apps/<app-name> dev` 直接启动指定应用,例如 `pnpm -C apps/layout dev`。
|
|
39
42
|
|
|
43
|
+
### 多应用并行启动
|
|
44
|
+
|
|
45
|
+
通过 `dev.preset.json` 配置预设,一条命令并行启动多个应用:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# 使用默认预设启动
|
|
49
|
+
pnpm dev:preset
|
|
50
|
+
|
|
51
|
+
# 使用指定预设
|
|
52
|
+
pnpm dev:preset full
|
|
53
|
+
|
|
54
|
+
# 查看所有预设
|
|
55
|
+
pnpm list:preset
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
预设配置文件 `dev.preset.json` 示例:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"presets": {
|
|
63
|
+
"full": {
|
|
64
|
+
"description": "启动所有应用",
|
|
65
|
+
"apps": ["layout", "subapp"]
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"default": "full"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
每个应用的日志会以不同颜色的前缀区分,按 `Ctrl+C` 同时停止所有应用。
|
|
73
|
+
|
|
74
|
+
详细说明请参考 [多应用并行启动文档](./docs/dev-preset.md)。
|
|
75
|
+
|
|
40
76
|
## 新建子应用
|
|
41
77
|
|
|
42
78
|
使用 Mico CLI 快速创建新的 React 子应用:
|
|
@@ -57,9 +93,11 @@ mico create subapp-react
|
|
|
57
93
|
│ └── layout/ # 主应用(qiankun master)
|
|
58
94
|
├── packages/ # 共享包目录
|
|
59
95
|
├── scripts/ # 构建与开发脚本
|
|
60
|
-
│ ├── dev.js #
|
|
96
|
+
│ ├── dev.js # 交互式启动脚本(单应用)
|
|
97
|
+
│ ├── dev-preset.js # 多应用并行启动脚本
|
|
61
98
|
│ ├── collect-dist.js # 构建产物收集
|
|
62
99
|
│ └── create-umi-app.sh # 创建新应用
|
|
100
|
+
├── dev.preset.json # 多应用启动预设配置
|
|
63
101
|
├── turbo.json # Turborepo 任务管道
|
|
64
102
|
├── pnpm-workspace.yaml # Workspace 包含范围
|
|
65
103
|
└── .editorconfig # 编辑器统一约束
|
|
@@ -59,7 +59,7 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
59
59
|
define: {
|
|
60
60
|
'process.env.NODE_ENV': 'development',
|
|
61
61
|
'process.env.APP_ID': '<%= projectName %>',
|
|
62
|
-
'process.env.API_BASE_URL': '',
|
|
62
|
+
'process.env.API_BASE_URL': 'https://dashboard-api-test.micoplatform.com',
|
|
63
63
|
'process.env.PROXY_SUFFIX': '/proxy/audit_svr',
|
|
64
64
|
'process.env.LOGIN_ENDPOINT':
|
|
65
65
|
'https://dashboard-api-test.micoplatform.com/api/yufu_login/',
|
|
@@ -6,7 +6,7 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
6
6
|
define: {
|
|
7
7
|
'process.env.NODE_ENV': 'testing',
|
|
8
8
|
'process.env.APP_ID': '<%= projectName %>',
|
|
9
|
-
'process.env.API_BASE_URL': '',
|
|
9
|
+
'process.env.API_BASE_URL': 'https://dashboard-api-test.micoplatform.com',
|
|
10
10
|
'process.env.PROXY_SUFFIX': '/proxy/audit_svr',
|
|
11
11
|
'process.env.LOGIN_ENDPOINT':
|
|
12
12
|
'https://dashboard-api-test.micoplatform.com/api/yufu_login/',
|
|
@@ -11,12 +11,12 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
11
11
|
define: {
|
|
12
12
|
'process.env.NODE_ENV': 'production',
|
|
13
13
|
'process.env.APP_ID': '<%= projectName %>',
|
|
14
|
-
'process.env.API_BASE_URL': '',
|
|
14
|
+
'process.env.API_BASE_URL': 'https://dashboard-api.micoplatform.com',
|
|
15
15
|
'process.env.PROXY_SUFFIX': '/proxy/audit_svr',
|
|
16
16
|
'process.env.LOGIN_ENDPOINT':
|
|
17
|
-
'https://dashboard-api
|
|
17
|
+
'https://dashboard-api.micoplatform.com/api/yufu_login/',
|
|
18
18
|
'process.env.REFRESH_ENDPOINT':
|
|
19
|
-
'https://dashboard-api
|
|
19
|
+
'https://dashboard-api.micoplatform.com/api/yufu_login/refresh/',
|
|
20
20
|
'process.env.EXTERNAL_LOGIN_PATH':
|
|
21
21
|
'https://micous-idp.cig.tencentcs.com/sso/xxxxxxx/cas',
|
|
22
22
|
},
|
|
@@ -198,7 +198,7 @@ wc -c apps/[子应用]/dist/umi.css
|
|
|
198
198
|
|
|
199
199
|
#### 原理
|
|
200
200
|
|
|
201
|
-
1. 主应用加载 @mico-platform/ui 并暴露到 `window.
|
|
201
|
+
1. 主应用加载 @mico-platform/ui 并暴露到 `window.micoUI`
|
|
202
202
|
2. 主应用的样式包含 `arco-theme` 属性选择器(基于 Arco)
|
|
203
203
|
3. 主应用切换主题时设置 `body[arco-theme="dark"]`
|
|
204
204
|
4. 子应用的 UI 组件(来自 window.micoUi)自动应用暗色样式
|
|
@@ -271,7 +271,7 @@ export const getRequest = () => mainAppProps?.request;
|
|
|
271
271
|
│ 主应用 (layout) │
|
|
272
272
|
│ ┌─────────────────────────────────────────────────────────┐│
|
|
273
273
|
│ │ 1. 打包并加载 React、ReactDOM、@mico-platform/ui ││
|
|
274
|
-
│ │ 2. 暴露到 window.React / window.ReactDOM / window.
|
|
274
|
+
│ │ 2. 暴露到 window.React / window.ReactDOM / window.micoUI ││
|
|
275
275
|
│ └─────────────────────────────────────────────────────────┘│
|
|
276
276
|
│ ↓ 共享 │
|
|
277
277
|
│ ┌─────────────────────────────────────────────────────────┐│
|
|
@@ -289,7 +289,7 @@ export const getRequest = () => mainAppProps?.request;
|
|
|
289
289
|
|
|
290
290
|
```typescript
|
|
291
291
|
// apps/layout/src/app.tsx
|
|
292
|
-
import * as
|
|
292
|
+
import * as micoUI from '@mico-platform/ui';
|
|
293
293
|
import React from 'react';
|
|
294
294
|
import ReactDOM from 'react-dom';
|
|
295
295
|
|
|
@@ -297,7 +297,7 @@ import ReactDOM from 'react-dom';
|
|
|
297
297
|
if (typeof window !== 'undefined') {
|
|
298
298
|
(window as any).React = React;
|
|
299
299
|
(window as any).ReactDOM = ReactDOM;
|
|
300
|
-
(window as any).
|
|
300
|
+
(window as any).micoUI = micoUI;
|
|
301
301
|
}
|
|
302
302
|
```
|
|
303
303
|
|
|
@@ -334,7 +334,7 @@ const config: ReturnType<typeof defineConfig> = {
|
|
|
334
334
|
externals: {
|
|
335
335
|
react: 'window.React',
|
|
336
336
|
'react-dom': 'window.ReactDOM',
|
|
337
|
-
'@mico-platform/ui': 'window.
|
|
337
|
+
'@mico-platform/ui': 'window.micoUI',
|
|
338
338
|
},
|
|
339
339
|
};
|
|
340
340
|
|
|
@@ -2,7 +2,7 @@ import { history, type RequestConfig } from '@umijs/max';
|
|
|
2
2
|
import { addGlobalUncaughtErrorHandler } from 'qiankun';
|
|
3
3
|
import { errorConfig } from './requestErrorConfig';
|
|
4
4
|
// 将 @mico-platform/ui 暴露到 window,供子应用 externals 使用
|
|
5
|
-
import * as
|
|
5
|
+
import * as micoUI from '@mico-platform/ui';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import ReactDOM from 'react-dom/client';
|
|
8
8
|
|
|
@@ -86,7 +86,7 @@ if (typeof window !== 'undefined') {
|
|
|
86
86
|
const win = window as unknown as Record<string, unknown>;
|
|
87
87
|
win.React = React;
|
|
88
88
|
win.ReactDOM = ReactDOM;
|
|
89
|
-
win.
|
|
89
|
+
win.micoUI = micoUI;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
// 初始化主题(在页面加载时立即执行,避免闪烁)
|