为了完成越来越复杂的网页应用,模块化发挥了越来越重要的作用。为了让模块化代码在浏览器中运行,模块打包工具成为了开发者必不可少的重要工具。
0 打包工具的前世今生
在 ES2015 发布之前,JavaScript 语言本身并不支持模块化,在众多的非官方模块化规范中,CommonJS 借势 Node.js 的流行成为了应用最为广泛的方案。然而,CommonJS 是为了构建浏览器之外的 JavaScript 项目而生的规范,想要在浏览器中运行 CommonJS 代码就必须对代码进行额外处理,这就是模块打包工具诞生的原因。
模块打包工具发展至今已经非常成熟,Browserify、Webpack 这些打包工具除了能够将 CommonJS 代码打包为浏览器可以运行的代码,还提供了代码分割、更多模块化规范支持等丰富的功能以及良好的开发体验。
CommonJS 的良好格局被 ES2015 模块化规范的出现打破了。原生的模块化规范相比第三方的模块化规范有许多无可取代的优势,可以确定的是 CommonJS 将会在不久的将来被 ES2015 所取代成为一段历史。而在 ES2015 普及的过程中,CommonJS 规范的模块打包工具可谓凭借 Babel 强行续命,发挥最后的余热。
1 「下一代」打包工具
Rollup 称自己为下一代打包工具,因为 Rollup 为 ES2015 模块化规范而生的。与当下流行的 CommonJS 打包规范打包工具不同,Rollup 可以直接打包符合 ES2015 模块化规范的代码,而并不需要将代码通过 Babel 转化为 CommonJS 模块化规范的形式。
2 为什么使用 Rollup
在目前 CommonJS 规范的打包工具拥有良好开发体验的情况下,为什么要使用 Rollup?或者说 Rollup 有什么优势?
首先,不同于目前流行的打包工具,Rollup 并不会为每个模块创建独立的函数作用域,而是将所有的代码放置于同一个作用域中,这使得代码的运行更有效率。
此外,得益于 ES2015 模块化规范的静态化导入特性,Rollup 可以通过 Tree-Shaking 操作对代码进行精简,从而得到提及更小的打包代码。关于 Tree-Shaking 的介绍,可以参考这篇文章。除了 Tree-Shaking,Rollup 还支持 Bindings 和 Cycles 这类高级特性。
最后,ES2015 已经是不可逆转的趋势,告别 Common Module,拥抱 ES Module 正在成为更多人的选择。
3 如何使用 Rollup
3.1 第一个 Rollup 打包文件
如果你熟悉 Browserify + Babel 或 Webpack + Babel 的开发模式,那么使用 Rollup 看起来再简单不过了,只需要使用 npm 全局安装 rollup,就可以通过命令行打包符合 ES2015 的文件了。
main.js:
import config from "./config.js"; |
config.js:
export default { |
只需要在命令行运行 rollup main.js -o bundle.js
就可以完成打包工作,其中 main.js 是入口文件,bundle.js 是输出文件,生成的打包文件将会是下面的样子:
bundle.js:
var config = { |
可以看到 Rollup 生成的代码非常简洁,整个文件并没有添加额外的函数作用域及代码,这便是 Rollup 一大优势。
3.2 更多配置项
很多时候我们的代码还会作为一个模块导出供其他模块使用,Rollup 虽然是一个 ES2015 模块打包器,但提供多种规范的模块导出 —— Rollup 支持导出 AMD、CommonJS、ES2015、Global 及 UMD 五种规范的打包文件,可以通过 rollup -f amd/cjs/es/iife/umd
来切换导出模块所使用的规范。
在使用 Global 及 UMD 规范时,导出的模块可能会被挂载到全局变量上,这时需要设置一个变量名用于模块挂载,通过 rollup -n
命令就可以定义模块名。
Rollup 同样提供了配置文件的功能,使用 rollup -c
即可读取 rollup.config.js 中的配置。
4 Rollup 开发实践
4.1 Rollup 引用 npm 资源
使用 ES2015 模块语法的 Rollup 在默认情况下是不支持 CommonJS 模块,这还会导致 npm 包在默认情况下也不能被 Rollup 支持。为了使用 npm 资源,我们需要通过 plugin 帮助 Rollup 支持 CommonJS 模块语法,这里用到的是 rollup-plugin-commonjs,另外,由于 Rollup 默认不会解析 node_modules 目录,还需要使用 rollup-plugin-node-resolve 来解析 npm 模块。
4.2 Rollup 结合 Babel
默认情况下,Babel 会将 ES2015 模块语法转化为 CommonJS 模块语法,这必然会导致基于 ES2015 模块化语法的 Rollup 无法正常工作,因此 Babel 需要进行特殊配置以配合 Rollup。
为了使用 Babel,我们首先要将 Babel 默认的 es2015 preset 替换为 es2015-rollup,这一 preset 不会编译模块化的相关语法,另外还会添加 Rollup 的一些依赖代码。最后只需要在 Rollup 中使用 rollup-plugin-babel,就可以让 Babel 与 Rollup 和睦共处。