Node 如何调用 vue-cli 打包
vue-cli 官方没有直接提供 api 来打包,一般大家也不会遇到需要用调用 api 来打包的场景,使用 vue-cli 提供的命令基本可以满足所有场景。那么如果需要使用 api 来批量打包该如何做呢?
我们先来了解下 vue-cli 自身是如何打包的。
先找到执行打包命令的入口文件。
https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/package.json
vue-cli-service.js 代码比较简单,整个打包过程可以概括为:初始化了一个 Service 类,然后直接执行实例的 run 方法就完成了整个打包动作。那么如果我们要自己打包,理论上也按这个流程就可以完成。
vue-cli-service 源码核心代码如下:
const Service = require('../lib/Service')
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
// 省略初始 cli 参数
service.run(command, args, rawArgv).catch(err => {
error(err)
process.exit(1)
})
接下来用一个例子来测试上面的方法是否可行。
使用 vue-cli 初始化一个项目。
vue create mybuild
这里我们希望通过调用非命令的方式,循环将 components 下的 vue 文件打包为三个库(--target=lib)。
新建一个打包文件 build.js,打包代码参考 vue-cli-service.js 的流程。
const path = require("path");
const fs = require("fs");
const Service = require("@vue/cli-service/lib/Service");
const { error } = require("@vue/cli-shared-utils");
const service = new Service(path.resolve(__dirname, "../"));
function pack(file, dest, buildArgs = ["--name", "index"]) {
return new Promise((resolve, reject) => {
const rawArgv = ["build", "--target", "lib", "--dest", dest, ...buildArgs, file];
const args = require("minimist")(rawArgv, {
boolean: [
// build
"modern",
"report",
"report-json",
"inline-vue",
"watch",
// serve
"open",
"copy",
"https",
// inspect
"verbose"
]
});
const command = args._[0];
service
.run(command, args, rawArgv)
.then(() => {
resolve();
})
.catch((err) => {
error(err);
reject(err);
});
});
}
Service 初始化需要传入项目根目录,因为一些打包的配置文件一般都放在项目根目录(比如 eslint,babel等)。
上面的 rawArgv 对应的是在使用命令方式打包时的命令参数,比如 --target、--dest,我们使用的是 api 调用方式,因此直接可以将参数给列出来,这里我们要打包为 lib,因此要在 rawArgv 中增加 --target lib,其他一些配置可以根据自己的需求来添加。
接下来就是循环调用 pack 来打包 components 下的所有文件,并输出到 dist 目录下。
async function build() {
const root = path.resolve(__dirname, "./src/components");
const files = await fs.promises.readdir(root);
for (let i = 0, j = files.length; i < j; i++) {
const file = files[i];
const entryFile = path.join(root, file);
const fileInfo = path.parse(entryFile);
const destDir = "./dist/" + fileInfo.name;
await pack(entryFile, destDir);
}
}
build();
执行
node build.js
打包后的文件如下图所示。
仔细分析 vue-cli-service 源码发现,打包的时候还可以自定义 vue.config.js 的路径,甚至文件名都可以随意指定,只需调整对应的环境变量即可。
process.env.VUE_CLI_SERVICE_CONFIG_PATH="配置文件路径"
比如我们在指定一个 components.config.js 用于打包 components 下的 vue 文件,配置方式和 vue.config.js 一样。
module.exports = {
productionSourceMap: false,
configureWebpack: {
externals: {
vue: {
commonjs: "vue",
commonjs2: "vue",
root: "Vue",
amd: "vue"
}
}
}
};
在打包方法里面修改环境变量。
async function build() {
process.env.VUE_CLI_SERVICE_CONFIG_PATH = "./components.config.js";
const root = path.resolve(__dirname, "./src/components");
const files = await fs.promises.readdir(root);
for (let i = 0, j = files.length; i < j; i++) {
const file = files[i];
const entryFile = path.join(root, file);
const fileInfo = path.parse(entryFile);
const destDir = "./dist/" + fileInfo.name;
await pack(entryFile, destDir);
}
}
再次打包,会发现 source map 文件没有再生成,说明指定的配置文件生效了。
这样就不会和项目的 vue.config.js 产生冲突。