@bams-app/ui-dev-server 0.0.8 → 0.1.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/bin/build-app.js +18 -5
- package/bin/build-umd.js +21 -3
- package/bin/ui-dev-server.js +35 -4
- package/package.json +18 -7
- package/utils.js +102 -2
- package/vue.config.base.js +33 -4
package/bin/build-app.js
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
|
-
const
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { getRootDir, getProjectPackageJson, parseCliArgs, resolveComponentInput, resolveEnvFile, loadProjectEnv, colorize } = require('../utils');
|
|
5
7
|
|
|
6
8
|
const rootDir = getRootDir();
|
|
7
9
|
const packageJson = getProjectPackageJson(rootDir);
|
|
8
10
|
|
|
9
11
|
async function main() {
|
|
10
|
-
const { componentName: rawComponentName, vueCliArgs } = parseCliArgs(process.argv);
|
|
12
|
+
const { componentName: rawComponentName, envFile, vueCliArgs } = parseCliArgs(process.argv);
|
|
11
13
|
const componentName = await resolveComponentInput(rawComponentName, rootDir, packageJson);
|
|
12
14
|
|
|
13
|
-
//
|
|
14
|
-
const
|
|
15
|
+
// 打包默认应用 .envs/.env.production(可用 --env <标识> 覆盖);项目缺少该文件时沿用当前进程环境
|
|
16
|
+
const envAlias = envFile || 'production';
|
|
17
|
+
const envFilePath = resolveEnvFile(envAlias, rootDir);
|
|
18
|
+
let env;
|
|
19
|
+
if (fs.existsSync(envFilePath)) {
|
|
20
|
+
env = loadProjectEnv(envAlias, rootDir);
|
|
21
|
+
} else if (envFile) {
|
|
22
|
+
console.error(colorize(`[build-app] 环境文件不存在: ${envFilePath}`, 'red'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
} else {
|
|
25
|
+
console.warn(colorize(`[build-app] 未找到 ${path.relative(rootDir, envFilePath)},将使用当前进程环境`, 'yellow'));
|
|
26
|
+
env = { ...process.env };
|
|
27
|
+
}
|
|
15
28
|
env.COMPONENT = componentName;
|
|
16
29
|
env.WORK_PROJECT_ROOT = rootDir;
|
|
17
30
|
env.NODE_ENV = 'production';
|
|
@@ -24,7 +37,7 @@ async function main() {
|
|
|
24
37
|
|
|
25
38
|
const child = spawn(process.execPath, [vueCliService, 'build', ...vueCliArgs], {
|
|
26
39
|
env,
|
|
27
|
-
cwd:
|
|
40
|
+
cwd: path.resolve(__dirname, '../'),
|
|
28
41
|
stdio: 'inherit'
|
|
29
42
|
});
|
|
30
43
|
|
package/bin/build-umd.js
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
-
const { getRootDir } = require('../utils');
|
|
6
|
+
const { getRootDir, resolveEnvFile, loadProjectEnv, colorize } = require('../utils');
|
|
7
7
|
|
|
8
8
|
// 解析命令行参数
|
|
9
9
|
const args = process.argv.slice(2);
|
|
10
10
|
let entryFile = '';
|
|
11
11
|
let outputDir = '';
|
|
12
12
|
let outputName = 'bams-components';
|
|
13
|
+
let envAlias = '';
|
|
13
14
|
|
|
14
15
|
// 处理参数
|
|
15
16
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -34,6 +35,11 @@ for (let i = 0; i < args.length; i++) {
|
|
|
34
35
|
outputName = args[i].split('=')[1];
|
|
35
36
|
} else if (args[i].startsWith('-n=')) {
|
|
36
37
|
outputName = args[i].split('=')[1];
|
|
38
|
+
} else if (args[i] === '--env') {
|
|
39
|
+
envAlias = args[i + 1];
|
|
40
|
+
i++;
|
|
41
|
+
} else if (args[i].startsWith('--env=')) {
|
|
42
|
+
envAlias = args[i].split('=')[1];
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
|
|
@@ -58,8 +64,20 @@ if (outputDir && !path.isAbsolute(outputDir)) {
|
|
|
58
64
|
outputDir = path.resolve(process.cwd(), outputDir);
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
//
|
|
62
|
-
const
|
|
67
|
+
// 打包默认应用 .envs/.env.production(可通过 --env 指定环境标识或 env 文件路径);项目缺少该文件时沿用当前进程环境
|
|
68
|
+
const resolvedEnvAlias = envAlias || 'production';
|
|
69
|
+
const envFilePath = resolveEnvFile(resolvedEnvAlias, rootDir);
|
|
70
|
+
let env;
|
|
71
|
+
if (fs.existsSync(envFilePath)) {
|
|
72
|
+
env = loadProjectEnv(resolvedEnvAlias, rootDir);
|
|
73
|
+
console.log(colorize(`[build-umd] Env file: ${path.relative(rootDir, envFilePath)}`, 'blue'));
|
|
74
|
+
} else if (envAlias) {
|
|
75
|
+
console.error(`❌ 环境文件不存在:${envFilePath}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
} else {
|
|
78
|
+
console.warn(`⚠️ 未找到 ${path.relative(rootDir, envFilePath)},将使用当前进程环境`);
|
|
79
|
+
env = { ...process.env };
|
|
80
|
+
}
|
|
63
81
|
env.WORK_PROJECT_ROOT = rootDir;
|
|
64
82
|
env.ENTRY_FILE = entryFile;
|
|
65
83
|
if (outputDir) env.OUTPUT_DIR = outputDir;
|
package/bin/ui-dev-server.js
CHANGED
|
@@ -2,17 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const { getRootDir, getProjectPackageJson, parseCliArgs, resolveComponentInput, colorize } = require('../utils');
|
|
5
|
+
const { getRootDir, getProjectPackageJson, parseCliArgs, resolveComponentInput, resolveEnvFile, listEnvAliases, loadProjectEnv, colorize } = require('../utils');
|
|
6
6
|
|
|
7
7
|
const rootDir = getRootDir();
|
|
8
8
|
const packageJson = getProjectPackageJson(rootDir);
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* 校验环境标识是否已指定
|
|
12
|
+
* - 已显式传入(位置参数 / --env),或环境已由 shared-env 注入(BAMS_ENV_FILE)时放行,
|
|
13
|
+
* 保证仓库内 dev:ui 链路行为不变
|
|
14
|
+
* - 项目内存在 .envs/.env.dev-* 却未指定时报错并列出可用环境,避免"静默无环境"
|
|
15
|
+
* - 项目内没有任何环境配置时仅提示,不阻塞启动
|
|
16
|
+
* @param {string} envInput - 环境标识或 env 文件路径
|
|
17
|
+
*/
|
|
18
|
+
function assertEnvSpecified(envInput) {
|
|
19
|
+
if (envInput || process.env.BAMS_ENV_FILE) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const aliases = listEnvAliases(rootDir);
|
|
24
|
+
if (aliases.length === 0) {
|
|
25
|
+
console.warn(colorize('[ui-dev-server] 未找到环境配置(.envs/.env.dev-*),将以无环境变量方式启动', 'yellow'));
|
|
26
|
+
console.warn(colorize('[ui-dev-server] 可先执行 bams-work env <标识> 创建环境配置', 'yellow'));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.error(colorize('[ui-dev-server] 未指定环境标识,启动已终止', 'red'));
|
|
31
|
+
console.error(colorize(`[ui-dev-server] 可用环境: ${aliases.join(', ')}`, 'yellow'));
|
|
32
|
+
console.error(colorize('[ui-dev-server] 用法: npm run dev:ui <环境标识> [组件名]', 'yellow'));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
10
36
|
async function main() {
|
|
11
|
-
const { componentName: rawComponentName, layout, vueCliArgs } = parseCliArgs(process.argv);
|
|
37
|
+
const { componentName: rawComponentName, layout, envFile, vueCliArgs } = parseCliArgs(process.argv);
|
|
38
|
+
assertEnvSpecified(envFile);
|
|
12
39
|
const componentName = await resolveComponentInput(rawComponentName, rootDir, packageJson);
|
|
13
40
|
|
|
14
|
-
//
|
|
15
|
-
const
|
|
41
|
+
// 环境标识对应的文件键优先于进程已有变量
|
|
42
|
+
const envFilePath = resolveEnvFile(envFile, rootDir);
|
|
43
|
+
const env = loadProjectEnv(envFile, rootDir);
|
|
44
|
+
if (envFilePath) {
|
|
45
|
+
console.log(colorize(`[ui-dev-server] Env file: ${path.relative(rootDir, envFilePath)}`, 'blue'));
|
|
46
|
+
}
|
|
16
47
|
env.COMPONENT = componentName;
|
|
17
48
|
env.LAYOUT = layout;
|
|
18
49
|
env.WORK_PROJECT_ROOT = rootDir;
|
package/package.json
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bams-app/ui-dev-server",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"serve": "node ./bin/ui-dev-server.js",
|
|
6
6
|
"build": "vue-cli-service build",
|
|
7
7
|
"build:umd": "node ./bin/build-umd.js",
|
|
8
8
|
"lint": "vue-cli-service lint"
|
|
9
9
|
},
|
|
10
|
-
"peerDependencies": {
|
|
11
|
-
"ant-design-vue": "^4.0.0",
|
|
12
|
-
"vue": "^3.5.24",
|
|
13
|
-
"vue-router": "^4.0.0"
|
|
14
|
-
},
|
|
15
10
|
"dependencies": {
|
|
16
11
|
"@babel/core": "^7.12.16",
|
|
17
12
|
"@babel/eslint-parser": "^7.12.16",
|
|
@@ -32,6 +27,7 @@
|
|
|
32
27
|
"@bams-app/permission": "*",
|
|
33
28
|
"@bams-app/router": "*",
|
|
34
29
|
"@bams-app/service": "*",
|
|
30
|
+
"@bams-app/shared-env": "*",
|
|
35
31
|
"@bams-app/store": "*",
|
|
36
32
|
"@bams-app/theme": "*",
|
|
37
33
|
"@bams-app/ui-business-table": "*",
|
|
@@ -46,15 +42,30 @@
|
|
|
46
42
|
"@bams-app/utils": "*",
|
|
47
43
|
"@bams-app/version-check": "*",
|
|
48
44
|
"@bams-app/websocket": "*",
|
|
45
|
+
"@ant-design/icons-vue": "^7.0.1",
|
|
49
46
|
"@vue/cli-plugin-babel": "~5.0.0",
|
|
50
47
|
"@vue/cli-service": "~5.0.0",
|
|
48
|
+
"ant-design-vue": "4.2.6",
|
|
49
|
+
"axios": "^1.13.2",
|
|
51
50
|
"core-js": "^3.8.3",
|
|
51
|
+
"dayjs": "^1.11.20",
|
|
52
|
+
"devextreme": "25.2.3",
|
|
53
|
+
"devextreme-exceljs-fork": "^4.4.8",
|
|
54
|
+
"devextreme-vue": "25.2.3",
|
|
55
|
+
"file-saver": "^2.0.5",
|
|
56
|
+
"flex.css": "^1.1.7",
|
|
52
57
|
"inquirer": "9",
|
|
58
|
+
"jsencrypt": "^3.5.4",
|
|
53
59
|
"less": "^4.5.1",
|
|
54
60
|
"less-loader": "^7.3.0",
|
|
61
|
+
"marked": "^17.0.4",
|
|
62
|
+
"pinia": "^3.0.4",
|
|
63
|
+
"pinia-plugin-persistedstate": "^4.7.1",
|
|
55
64
|
"raw-loader": "^4.0.2",
|
|
56
65
|
"sass": "^1.97.3",
|
|
57
|
-
"sass-loader": "^10.1.1"
|
|
66
|
+
"sass-loader": "^10.1.1",
|
|
67
|
+
"vue": "^3.5.24",
|
|
68
|
+
"vue-router": "4"
|
|
58
69
|
},
|
|
59
70
|
"files": [
|
|
60
71
|
"bin/",
|
package/utils.js
CHANGED
|
@@ -291,16 +291,21 @@ function colorize(text, color) {
|
|
|
291
291
|
|
|
292
292
|
/**
|
|
293
293
|
* 解析命令行参数
|
|
294
|
+
* 位置参数:第 1 个为环境标识(等价 --env),第 2 个为组件名(等价 --component)
|
|
295
|
+
* 即 `npm run dev:ui demo` → 环境 demo,`npm run dev:ui demo ui-order-list` → 环境 demo + 组件 ui-order-list
|
|
294
296
|
* @param {string[]} argv - process.argv
|
|
295
297
|
* @returns {Object} 解析结果
|
|
296
298
|
* @returns {string} returns.componentName - 组件名
|
|
297
299
|
* @returns {string} returns.layout - 布局类型
|
|
300
|
+
* @returns {string} returns.envFile - 环境标识或 env 文件路径(第 1 个位置参数或 --env,可为空)
|
|
298
301
|
* @returns {string[]} returns.vueCliArgs - 传递给 Vue CLI 的参数
|
|
299
302
|
*/
|
|
300
303
|
function parseCliArgs(argv) {
|
|
301
304
|
const args = argv.slice(2);
|
|
302
305
|
let componentName = 'ui-component-demo';
|
|
303
306
|
let layout = 'pc';
|
|
307
|
+
let envFile = '';
|
|
308
|
+
let envFromFlag = false;
|
|
304
309
|
const vueCliArgs = [];
|
|
305
310
|
|
|
306
311
|
let i = 0;
|
|
@@ -327,7 +332,24 @@ function parseCliArgs(argv) {
|
|
|
327
332
|
} else if (arg.startsWith('-l=')) {
|
|
328
333
|
layout = arg.split('=')[1];
|
|
329
334
|
i++;
|
|
335
|
+
// --env 或 -e 参数:环境标识(如 demo)或 env 文件路径
|
|
336
|
+
} else if (arg === '--env' || arg === '-e') {
|
|
337
|
+
envFile = args[i + 1];
|
|
338
|
+
envFromFlag = true;
|
|
339
|
+
i += 2;
|
|
340
|
+
} else if (arg.startsWith('--env=')) {
|
|
341
|
+
envFile = arg.split('=')[1];
|
|
342
|
+
envFromFlag = true;
|
|
343
|
+
i++;
|
|
344
|
+
} else if (arg.startsWith('-e=')) {
|
|
345
|
+
envFile = arg.split('=')[1];
|
|
346
|
+
envFromFlag = true;
|
|
347
|
+
i++;
|
|
330
348
|
// Vue CLI 参数(以 -- 开头)
|
|
349
|
+
} else if (arg === '--') {
|
|
350
|
+
// 分隔符:其后参数原样透传给 vue-cli-service(npm run dev -- 会额外透传一个 --)
|
|
351
|
+
vueCliArgs.push(...args.slice(i + 1));
|
|
352
|
+
break;
|
|
331
353
|
} else if (arg.startsWith('--')) {
|
|
332
354
|
vueCliArgs.push(arg);
|
|
333
355
|
// 处理带值的选项
|
|
@@ -337,9 +359,13 @@ function parseCliArgs(argv) {
|
|
|
337
359
|
} else {
|
|
338
360
|
i++;
|
|
339
361
|
}
|
|
340
|
-
//
|
|
362
|
+
// 其他参数:位置参数(未显式传 --env 时,第 1 个 = 环境标识;其余 = 组件名)
|
|
341
363
|
} else {
|
|
342
|
-
|
|
364
|
+
if (!envFromFlag && envFile === '') {
|
|
365
|
+
envFile = arg;
|
|
366
|
+
} else {
|
|
367
|
+
componentName = arg;
|
|
368
|
+
}
|
|
343
369
|
i++;
|
|
344
370
|
}
|
|
345
371
|
}
|
|
@@ -347,10 +373,81 @@ function parseCliArgs(argv) {
|
|
|
347
373
|
return {
|
|
348
374
|
componentName,
|
|
349
375
|
layout,
|
|
376
|
+
envFile,
|
|
350
377
|
vueCliArgs
|
|
351
378
|
};
|
|
352
379
|
}
|
|
353
380
|
|
|
381
|
+
/**
|
|
382
|
+
* 将环境标识解析为 env 文件绝对路径
|
|
383
|
+
* - 路径形式(含路径分隔符,或以 .env 开头):相对项目根解析
|
|
384
|
+
* - production:映射为 <rootDir>/.envs/.env.production(打包使用,开发不适用)
|
|
385
|
+
* - 其他(环境标识,如 demo):映射为 <rootDir>/.envs/.env.dev-<标识>
|
|
386
|
+
* @param {string} envInput - 环境标识或 env 文件路径
|
|
387
|
+
* @param {string} rootDir - 项目根目录
|
|
388
|
+
* @returns {string} env 文件绝对路径,未传时返回空字符串
|
|
389
|
+
*/
|
|
390
|
+
function resolveEnvFile(envInput, rootDir) {
|
|
391
|
+
if (!envInput) {
|
|
392
|
+
return '';
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const isPathLike = envInput.includes('/')
|
|
396
|
+
|| envInput.includes('\\')
|
|
397
|
+
|| path.basename(envInput).startsWith('.env');
|
|
398
|
+
|
|
399
|
+
if (isPathLike) {
|
|
400
|
+
return path.resolve(rootDir, envInput);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const fileName = envInput === 'production' ? '.env.production' : `.env.dev-${envInput}`;
|
|
404
|
+
return path.resolve(rootDir, '.envs', fileName);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* 列出项目可用的开发环境标识(.envs/.env.dev-*)
|
|
409
|
+
* @param {string} rootDir - 项目根目录
|
|
410
|
+
* @returns {string[]} 环境标识列表
|
|
411
|
+
*/
|
|
412
|
+
function listEnvAliases(rootDir) {
|
|
413
|
+
const envDir = path.resolve(rootDir, '.envs');
|
|
414
|
+
if (!fs.existsSync(envDir)) {
|
|
415
|
+
return [];
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return fs.readdirSync(envDir)
|
|
419
|
+
.filter((name) => name.startsWith('.env.dev-') && !name.endsWith('.local'))
|
|
420
|
+
.map((name) => name.replace('.env.dev-', ''))
|
|
421
|
+
.sort();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* 按环境标识加载环境文件(dev/build 共用)
|
|
426
|
+
* - 环境标识为空时返回当前进程环境(不做任何加载)
|
|
427
|
+
* @param {string} envInput - 环境标识或 env 文件路径
|
|
428
|
+
* @param {string} rootDir - 项目根目录
|
|
429
|
+
* @returns {Object} 环境变量对象
|
|
430
|
+
*/
|
|
431
|
+
function loadProjectEnv(envInput, rootDir) {
|
|
432
|
+
if (!envInput) {
|
|
433
|
+
return { ...process.env };
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const envFilePath = resolveEnvFile(envInput, rootDir);
|
|
437
|
+
if (!fs.existsSync(envFilePath)) {
|
|
438
|
+
throw new Error(`环境文件不存在: ${envFilePath}`);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
let loadEnv;
|
|
442
|
+
try {
|
|
443
|
+
({ loadEnv } = require('@bams-app/shared-env/lib/env-loader'));
|
|
444
|
+
} catch (err) {
|
|
445
|
+
throw new Error(`加载环境文件需要安装 @bams-app/shared-env(${err.message})`);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return loadEnv(rootDir, envFilePath);
|
|
449
|
+
}
|
|
450
|
+
|
|
354
451
|
/**
|
|
355
452
|
* 判断输入是否为文件系统路径
|
|
356
453
|
* @param {string} input - 输入字符串
|
|
@@ -460,6 +557,9 @@ module.exports = {
|
|
|
460
557
|
toCamelComponentName,
|
|
461
558
|
colorize,
|
|
462
559
|
parseCliArgs,
|
|
560
|
+
resolveEnvFile,
|
|
561
|
+
listEnvAliases,
|
|
562
|
+
loadProjectEnv,
|
|
463
563
|
isFileSystemPath,
|
|
464
564
|
promptForCandidate,
|
|
465
565
|
resolveComponentInput
|
package/vue.config.base.js
CHANGED
|
@@ -10,13 +10,41 @@ const builtinProxy = Object.fromEntries(
|
|
|
10
10
|
['/bams-assets', '/bams-ui-umd', '/bams-app', '/admin-api', '/preview'].map((p) => [p, { target: process.env.PROXY_TARGET }])
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* 加载项目级自定义代理配置(项目根 .proxy.js,可选,不存在时返回空对象)
|
|
15
|
+
* 支持两种导出形式:
|
|
16
|
+
* - 对象:module.exports = { proxy: { '/my-api': { target: 'http://192.168.1.100:8080' } } }
|
|
17
|
+
* - 函数:module.exports = ({ env, projectRoot }) => ({ proxy: { ... } })
|
|
18
|
+
* 加载失败时告警并回退为空配置,不阻断开发服务启动
|
|
19
|
+
* @param {string} rootDir 项目根目录
|
|
20
|
+
* @param {Object} [env=process.env] 环境变量对象,透传给函数形式的导出
|
|
21
|
+
* @returns {Object} devServer.proxy 片段
|
|
22
|
+
*/
|
|
23
|
+
function loadProjectProxy(rootDir, env = process.env) {
|
|
24
|
+
const filePath = path.join(rootDir, '.proxy.js');
|
|
25
|
+
|
|
26
|
+
if (!fs.existsSync(filePath)) {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const loaded = require(filePath);
|
|
32
|
+
const resolved = typeof loaded === 'function' ? loaded({ env, projectRoot: rootDir }) : loaded;
|
|
33
|
+
console.log(`[ui-dev-server] 已加载项目代理配置: ${path.basename(filePath)}`);
|
|
34
|
+
return (resolved || {}).proxy || {};
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.warn(`[ui-dev-server] 项目代理配置加载失败,已忽略: ${err.message}`);
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
13
41
|
/**
|
|
14
42
|
* 生成通用基础配置(原仓库根 vue.config.js 的核心逻辑)
|
|
15
43
|
* - externals(vue / vue-router / pinia)
|
|
16
44
|
* - md 文件 raw-loader
|
|
17
45
|
* - @components-entry 动态别名(存在 build-components-entry.js 时指向它,否则指向空入口)
|
|
18
46
|
* - @configurable/* 可配置组件别名(基于环境变量与默认插槽映射)
|
|
19
|
-
* - devServer
|
|
47
|
+
* - devServer 代理合并(devServer 配置 > 项目根 .proxy.js > 内置默认补充缺失前缀)
|
|
20
48
|
* @param {Object} [options]
|
|
21
49
|
* @param {string} options.rootDir 项目根目录
|
|
22
50
|
* @param {Object} options.packageJson 项目根 package.json
|
|
@@ -28,8 +56,9 @@ function getBaseConfig(options = {}) {
|
|
|
28
56
|
const packageJson = options.packageJson || getProjectPackageJson(rootDir);
|
|
29
57
|
const devServer = options.devServer || {};
|
|
30
58
|
|
|
31
|
-
//
|
|
32
|
-
|
|
59
|
+
// 代理优先级(同名覆盖,前者优先):options.devServer.proxy > 项目根 .proxy.js > 内置默认
|
|
60
|
+
// 键序即匹配序(webpack-dev-server 按插入顺序匹配前缀),项目级 key 在前,内置默认仅补充缺失前缀
|
|
61
|
+
const devProxy = { ...loadProjectProxy(rootDir), ...(devServer.proxy || {}) };
|
|
33
62
|
const mergedProxy = Object.fromEntries([
|
|
34
63
|
...Object.entries(devProxy),
|
|
35
64
|
...Object.entries(builtinProxy).filter(([k]) => !(k in devProxy)),
|
|
@@ -72,4 +101,4 @@ function getBaseConfig(options = {}) {
|
|
|
72
101
|
};
|
|
73
102
|
}
|
|
74
103
|
|
|
75
|
-
module.exports = { getRootDir, getProjectPackageJson, getBaseConfig };
|
|
104
|
+
module.exports = { getRootDir, getProjectPackageJson, getBaseConfig, loadProjectProxy };
|