「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战」
前言
最近我们介绍了 rollup 的自定义打包过程以及它简单的一个使用,学习一个技术,最好的方法就是在自己使用了以后,去看一下别的优秀的项目是如何去使用它的,再来对比一下自己的使用,在这其中就是不断的学习的一个过程。
所以今天我们就来介绍一下 rollup 在 Vue2 中是如何去应用的。
build 命令
首先看一个开源项目,我们需要先去看一下项目的 package.json,build一般是作为我们项目的打包命令,那么在 scripts 我们也能够看到 Vue 的打包命令运行了一个 js文件:
并且不同的打包命令也都是在这个命令的基础上添加后缀生成的,那么我们就可以先去看一下 scripts 底下的 build.js 文件:
bulid.js
在引入的依赖中能够一眼看到,在这里引入了 rollup,这个依赖底下的 rollup.rollup 和 generate 方法就是我们要去找的打包方法,至于为什么要找这两个方法,不清楚的可以看一下 rollup 官方文档中 JavaScript API 的教程介绍:
在得知这两个方法就是打包方法之后,我们就能够去寻找整个项目打包的输入和输出,rollup.rollup 方法需要传入打包的输入选项,generate 方法则是需要传入输出选项,两个选项可有的配置项如下:
inputOptions = {
// 核心参数
input, // 唯一必填参数
external,
plugins,
// 高级参数
onwarn,
cache,
// 危险参数
acorn,
context,
moduleContext,
legacy
};
outputOptions = {
// 核心参数
file, // 若有bundle.write,必填
format, // 必填
name,
globals,
// 高级参数
paths,
banner,
footer,
intro,
outro,
sourcemap,
sourcemapFile,
interop,
// 危险区域
exports,
amd,
indent
strict
};
然后在下方我们也能够去找到打包输入和输出配置项传入的地方
接着我们先来看一下输入配置项 config 一路往上就能够找到,config 是 builds 属性中的 [built] 属性
builds 属性是由 config.js 文件传递过来的。
config.js
跟着方法我们寻找到 config.js 文件的底部:
if (process.env.TARGET) {
module.exports = genConfig(process.env.TARGET);
} else {
exports.getBuild = genConfig;
exports.getAllBuilds = () => Object.keys(builds).map(genConfig);
}
或许当前我们不清楚这个判断分支的作用是什么,但是没有关系,我先去关心我们需要的部分,比较关键的也就是 genConfig 这个函数。
在 genConfig 函数内部会从一个设定好的 builds 对象中,获取当前对应的构建配置对象。
function genConfig(name) {
const opts = builds[name];
const config = {
input: opts.entry,
external: opts.external,
plugins: [flow(), alias(Object.assign({}, aliases, opts.alias))].concat(
opts.plugins || []
),
output: {
file: opts.dest,
format: opts.format,
banner: opts.banner,
name: opts.moduleName || "Vue",
},
onwarn: (msg, warn) => {
if (!/Circular/.test(msg)) {
warn(msg);
}
},
};
// 省略部分代码
return config;
然后在每个构建配置对象中,就会去定义不同的打包格式需要的不同的参数,分别有 entry 入口文件,dist 输出文件,format 输出格式,env 环境 等打包配合参数。
这里我们拿第一项来看一下:
const builds = {
// Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify
"web-runtime-cjs-dev": {
entry: resolve("web/entry-runtime.js"),
dest: resolve("dist/vue.runtime.common.dev.js"),
format: "cjs",
env: "development",
banner,
},
...
}
其中的 banner 定义了打包进行的时间和 Vue 的一个版本:
const banner =
"/*!\n" +
` * Vue.js v${version}\n` +
` * (c) 2014-${new Date().getFullYear()} Evan You\n` +
" * Released under the MIT License.\n" +
" */";
在看到入口的时候我们会发现,项目中并没有 web 目录,那么这个入口文件在什么地方呢?
其实入口文件只是利用 rolup 的 alias 插件取了个别名,具体的映射规则写在了 scripts/alias.js 文件中:
根据上面的映射规则,我们就能够找到对应的路径,这样就能够拿到对象的构建配置,然后我们就可以回到打包的文件 build.js 中去
build.js
在获得配置对象之后,我们就能够调用 rollup 的 API 来进行打包的操作
这里要注意,Vue 并未使用 rollup 提供的 write 方法,而是自己定义了 write 方法,但是他们的作用都是相同的,都是用来生成文件的:
function write(dest, code, zip) {
return new Promise((resolve, reject) => {
function report(extra) {
console.log(
blue(path.relative(process.cwd(), dest)) +
" " +
getSize(code) +
(extra || "")
);
resolve();
}
fs.writeFile(dest, code, (err) => {
if (err) return reject(err);
if (zip) {
zlib.gzip(code, (err, zipped) => {
if (err) return reject(err);
report(" (gzipped: " + getSize(zipped) + ")");
});
} else {
report();
}
});
});
}
然后我们看完 bulid 命令,会发现后面还有两个和 bulid 很相似的命令,分别是:
"build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer",
"build:weex": "npm run build -- weex",
它们则只是在 bulid 的基础上加了一层过滤,可以在 bulid.js 的上方看到逻辑:
let builds = require("./config").getAllBuilds();
// filter builds via command line arg
if (process.argv[2]) {
const filters = process.argv[2].split(",");
builds = builds.filter((b) => {
return filters.some(
(f) => b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1
);
});
} else {
// filter out weex builds by default
builds = builds.filter((b) => {
return b.output.file.indexOf("weex") === -1;
});
}
那么到这里我们就介绍完了 bulid 命令,接下来让我们看一下 dev 命令是如何执行的
dev 命令
dev 命令和 bulid 略有不同,我们也可以在 package.json 中去看到它:
可以看出来它是直接通过运行 rollup 来执行的,其中包含一些 rollup 的配置项:
-
-c:指定rollup打包的配置文件 -
-w:开启监听模式,当文件发生变化的时候,会自动进行打包 -
--environment:设置环境变量,之后可以通过process.env来获取这个配置
由 rollup 的 -c 配置项,我们得知配置文件为 scripts/config.js
在 scripts/config.js 文件的最下方有一个分支,刚刚在 build 命令中我们并没有去分析它,但是现在通过 dev 命令,我们很容易就能够看出来,这个分支是用于区分不同的打包获取不同配置,如果process.env 中存在 TARGET 这个属性,则会单独执行 genConfig 方法,并且将不同的环境变量当成参数传入进去,然后结合我们上面介绍过了 genConfig 方法,我们就可以根据不同的传入参数来获得不同的构建配置项。
到这里我们就介绍完了 Vue 是如何通过 rollup 进行打包的。
总结
本文稍微介绍了 Vue 通过 rollup 进行打包的一个大致流程,这只是 rollup 在 Vue2 中的一个应用, rollup 的打包还被应用在很多其他的出色开源项目当中,具体我们可以之后再来展开相关的学习。