让 Vue 使用指定配置文件进行构建
当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »
坑
Head Pic: #凯尔希 「梦想」 by キョウケン - pixiv
在 Vue 项目中,npm script 里通常用vue-cli-service build
来构建成品,该命令默认会使用vue.config.js
作为配置文件
但如果我们有在一个 Vue 项目中使用多个配置文件来构建不同成品的需求,该怎么办
可惜非常不人性化的是,vue-cli-service
并没有设计支持使用类似-c configFile
这样的参数来指定使用其它配置文件,那么还有其它办法么
VUE_CLI_SERVICE_CONFIG_PATH
环境变量
还好,经过搜索,我发现vue-cli-service
是支持使用VUE_CLI_SERVICE_CONFIG_PATH
环境变量来自定义配置文件的,我们可以添加一个 npm script 像下面这样(Unix 下)
VUE_CLI_SERVICE_CONFIG_PATH=my.vue.config.js vue-cli-service build
然而我实际执行确报错“找不到模块my.vue.config.js
”
看了下vue-cli-service
的源码,获取配置文件的部分是这样的
// In loadUserOptions()
const configPath = (
process.env.VUE_CLI_SERVICE_CONFIG_PATH ||
path.resolve(this.context, 'vue.config.js')
)
if (fs.existsSync(configPath)) {
try {
fileConfig = require(configPath)
if (typeof fileConfig === 'function') {
fileConfig = fileConfig()
}
if (!fileConfig || typeof fileConfig !== 'object') {
error(
`Error loading ${chalk.bold('vue.config.js')}: should export an object or a function that returns object.`
)
fileConfig = null
}
} catch (e) {
error(`Error loading ${chalk.bold('vue.config.js')}:`)
throw e
}
}
可以看到,configPath
会直接取环境变量作为 id 来require
,而不会像默认的vue.config.js
一样根据上下文来计算绝对路径
虽然看似非常反人类,但仔细想想也能理解这是出于安全考虑
那么解决方法就显而易见了,传个绝对路径进去,例如在 Unix 下可以利用$PWD
环境变量
VUE_CLI_SERVICE_CONFIG_PATH=$PWD/my.vue.config.js vue-cli-service build
但这衍生出另一个问题,最直接的说,Windows 下没有$PWD
,而是%cd%
,虽然我们能利用cross-env
解决不同操作系统下环境变量设置方式不同的问题,却无法解决 Windows 与 Unix 系统环境变量获取方式不同的问题
既然是 node,就用 node 解决
一拍大腿之后,曲线救国的方案就出来了,我们可以直接用 node 获取配置的绝对路径,然后作为环境变量来执行npm run build
在 node 中执行命令就要请child_process
出场了,梳理一下我们的需求:
- 执行
npm run build
- 传入
VUE_CLI_SERVICE_CONFIG_PATH
环境变量 - 维持原本的输出形式
阅读其文档,最终我选用 spawnSync 方法,相关参数如下
child_process.spawnSync(command[, args][, options])
command <string>
The command to run.args <string[]>
List of string arguments.options <Object>
shell <boolean> | <string>
Iftrue
, runscommand
inside of a shell. Uses'/bin/sh'
on Unix, andprocess.env.ComSpec
on Windows. A different shell can be specified as a string. See Shell Requirements and Default Windows Shell. Default:false
(no shell).stdio <string> | <Array>
Child's stdio configuration.env <Object>
Environment key-value pairs. Default: process.env.
值得说明的是 options.stdio 这一参数,其中有一条说明
'inherit'
: Pass through the corresponding stdio stream to/from the parent process. In the first three positions, this is equivalent toprocess.stdin
,process.stdout
, andprocess.stderr
, respectively. In any other position, equivalent to'ignore'
.
这正是我们想要的,将子进程的输入输出原封不动的传回给父进程,这样一来体验就与直接执行命令无异(指各种命令行动画和文字颜色这种)
所以最终我们可以像下面这样写个,比如说myBuild.js
const { spawnSync } = require('child_process');
const { resolve } = require('path');
spawnSync('npm', ['run', 'build'], {
shell: true,
env: {
...process.env, // 要记得导入原本的环境变量
VUE_CLI_SERVICE_CONFIG_PATH: resolve(__dirname, 'my.vue.config.js'),
},
stdio: 'inherit',
});
然后我们就可以添加一个 npm script 了,"build:my": "node myBuild.js"
拓展
我们可以做的更通用化一点,接受一个参数来指定配置文件,做到可以写成"build:my": "node build.js my.vue.config.js"
这样的效果,这里就不详细说了