现象描述
分别执行cross-env UMI_ENV=test max build
和cross-env UMI_ENV=production max build
,在config/config.ts
中headScripts
的首个资源加载存在差异。production
会丢失首个资源,而test
不会。
执行环境
@umijs/max@4.0.78
分析
因为主要是配置文件方向的问题,所以从配置文件入手,定位到getUserConfig函数:
ts
getUserConfig() {
const configFiles = Config.getConfigFiles({
mainConfigFile: this.mainConfigFile,
env: this.opts.env,
specifiedEnv: this.opts.specifiedEnv,
});
return Config.getUserConfig({
configFiles: getAbsFiles({
files: configFiles,
cwd: this.opts.cwd,
}),
});
}
这里的configFiles
,当执行cross-env UMI_ENV=production max build
时是:
js
[
'/config/config.ts',
'/config/config.production.ts',
'/config/config.prod.ts',
'/config/config.prod.production.ts'
]
当执行cross-env UMI_ENV=test max build
时是:
js
[
'/config/config.ts',
'/config/config.test.ts',
'/config/config.prod.ts',
'/config/config.prod.test.ts'
]
当执行max build
时是:
js
[
'/config/config.ts',
'/config/config.prod.ts'
]
很显然,无论是拿种情况,都会不止加载一个config/config.ts
文件,而是会根据env
来加载额外文件,并且把这些文件内容用lodash.merge
做 合并 处理。
而我们在/config/
下一共有两个配置文件,/config/config.ts
和/config/config.production.ts
,当指定了env
为production
时,会加载/config/config.production.ts
文件并与/config/config.ts
文件用lodash.merge
做内容合并处理。而我们在这两个文件中都配置了headScripts
,并且/config/config.production.ts
中的headScripts
恰好是配置了一个元素,于是导致合并的时候/config/config.ts
中的headScripts
第一个元素因为被覆盖而丢失。
丢失的原因是,lodash.merge 的合并处理,对于字符串数组来说,合并会导致相同位置的内容被替换,如:
js
const lodash = require('lodash');
lodash.merge(['1', '2', '3'], ['21']);
// 结果是:[ '21', '2', '3' ]
结论
执行build
命令时指定了env
,加载了多个config
文件,这些文件又配置了同一个字段,导致相同字段内容被覆盖