让 Vue 使用指定配置文件进行构建

887 字
4 分钟
让 Vue 使用指定配置文件进行构建
让 Vue 使用指定配置文件进行构建

坑

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 下)

Terminal window
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环境变量

Terminal window
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出场了,梳理一下我们的需求:

  1. 执行npm run build
  2. 传入VUE_CLI_SERVICE_CONFIG_PATH环境变量
  3. 维持原本的输出形式

阅读其文档,最终我选用 spawnSync 方法,相关参数如下

child_process.spawnSync(command[, args][, options])

  • command <string> The command to run.
  • args <string[]> List of string arguments.
  • options <Object>
    • shell <boolean> | <string> If true, runs command inside of a shell. Uses '/bin/sh' on Unix, and process.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 to process.stdin, process.stdout, and process.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"这样的效果,这里就不详细说了

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

让 Vue 使用指定配置文件进行构建
https://moe.best/posts/vue-build-from-specified-config/
作者
神代綺凛
发布于
2020-03-21
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
神代綺凛
专业咕咕
分类
标签
站点统计
文章
107
分类
15
标签
269
总字数
140,468
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
EdgeOne Pages
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录