神代綺凛

让 Vue 使用指定配置文件进行构建
扫描右侧二维码阅读全文
21
2020/03

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

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

  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"这样的效果,这里就不详细说了

搬瓦工VPS优惠套餐,建站稳如狗,支持支付宝,循环出账94折优惠码BWH3HYATVBJW
年付$47CN2线路,1核/1G内存/20G硬盘/1T@1Gbps【点击购买
季付$47CN2 GIA线路,1核/1G内存/20G硬盘/1T@2.5Gbps【点击购买
Last modification:May 3rd, 2020 at 07:33 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment Cancel reply

4 comments

  1. 风继续吹  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 105.0.0.0(Google Chrome 105.0.0.0)
    递茶+1
  2. Lemon  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 106.0.0.0(Google Chrome 106.0.0.0)
    时隔两年,没想到公司居然有业务要用上,所以回来看看大佬的文章
  3. zhedream  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 89.0.4389.72(Google Chrome 89.0.4389.72)
    666 , get 了
  4. 妖怪  Windows 7 x64 Edition(Windows 7 x64 Edition) / Google Chrome 78.0.3904.108(Google Chrome 78.0.3904.108)
    给大佬递茶OωO