一、 为什么要用模块化
更好的代码组织方式
如果单个文件越来越大,维护起来出错的几率也会越来越大。模块式的开发,一个文件就是一个模块,控制了文件的粒度,每个模块可以专注于一个功能。
更好的依赖处理
不再需要手动排序多个 <script>标签引用顺序,模块加载器已经帮你做好了。
多人协作互不干扰
和他人合作的时候,经常修改同一个文件?很容易引起冲突?模块化呀。
性能优化
模块化后的代码可以合成一个单一的文件进行部署,减少`HTTP`请求数
... 等等
二、为什么要使用 Rollup 打包工具?
简单做一个测试, 我们准备一个 module.js 文件和 entry.js 文件, 分别使用 Rollup 和 Webpack 打包。
package.json 如下:
![](https://img-blog.csdnimg.cn/img_convert/82d4f633451fc4428ec517812573a745.png)
module.js 如下:
![](https://img-blog.csdnimg.cn/img_convert/3d7a17fe1fb3c2a98997ec5cb28e2948.png)
entry.js 如下:
rollup.config.js 如下:
![](https://img-blog.csdnimg.cn/img_convert/42c9467b797d15d112cd7987fa7dae97.png)
webpack.config.js 如下:
![](https://img-blog.csdnimg.cn/img_convert/58f619e5991d28217a8482509ec77a06.png)
1. Rollup 可以打出更快更小的包,即使在最坏的情况下,它仍然会小于其他工具产生的捆绑。如图:
Webpack 打包后的 webpack3.0_bundle.js 文件约 3k, 而 Rollup 打包后的 bundle_rollup_iife.js 文件只有1k。
![](https://img-blog.csdnimg.cn/img_convert/85f78b4fca75bf1fe0ac941c2c8e67f2.png)
2. 杀手锏——只导出你需要的
Rollup 是第一个提出 Tree Shaking 的打包工具。想对 Tree Shaking 有更全面的了解,推荐阅读 Rich_Harris 的 [Tree-shaking versus dead code elimination](https://medium.com/@Rich_Harris/tree-shaking-versus-dead-code-elimination-d3765df85c80)。简单来说,Rollup 会静态分析你所引入的模块,去掉没有真正被用到的部分,只引入你需要的部分,减少项目的体积。
通过执行 npm run webpack , 我们得到了 Webpack 打包后的 webpack3.0_bundle.js文件中部分代码截图:
通过执行 npm run rollup -- -c , 我们得到了 Rollup 打包后的 bundle_rollup_iife.js 文件内容:
我们 Rollup 打包后的文件并没有输出 我们没有调用的函数 weDontWant。
此外, RollupJS 打包会将所有模块打包在一个大的闭包内,从而使代码在浏览器中具有更快的执行速度。
补充说明:Webpack2.0 已经支持 Tree Shaking, 但配置较为复杂。配置方法可以[参考官网](Tree Shaking)
Webpack 3.0 新增 作用域提升 配置。由于作用域提升会移除模块外的函数包装,你可以看到一些小体积的改进。然而,更显著的改进是 Javascript 在浏览器中加载的速度。
3. Rollup 是基于ES6 实现的代码模块化
Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块是 ES6 语法的一部分, ES6 语法是标准化的语言。所以 ES6 模块编写的代码是不会过时的。即便不是这样,也有很多喜欢 ES6 模块的理由。
关于全面的介绍,推荐阅读 [Axel Rauschmayer](Profile): [ECMAScript 6模块:最终语法](ECMAScript 6 modules: the final syntax)
ES6 的部分功能:
- 语法更好
- 模块导出的是绑定,而不是值。
- 支持循环依赖
来看一段代码:
CommonJS 写法如下:
![](https://img-blog.csdnimg.cn/img_convert/b2f514d68383b96958721070e3446201.png)
count 被 exports,但是 value 却被锁定了!或者说 count = counter.count, 但 count 的值却没有被改变。
但按照 ES6 的写法:
![](https://img-blog.csdnimg.cn/img_convert/07a988d17647da111d801561ab3c49fa.png)
我们得到了我们想要的结果。ES6 模块导出的是绑定,而不是值。
接下来我们看一下,周期性循环依赖(github.com/rollup/rollup/wiki/Cycles)
关于周期性循环依赖,我们再来看一段代码:
我们经常会听到大家说,不要写循环依赖,那是一种不好的编码方式,会制造很多垃圾。特别是在你写递归函数的时候。大家为什么会这样说?因为对于 AMD 和 CommonJS 来说,编译循环依赖是一个巨大的挑战。但对于 ES6 来说,就容易许多。
Rollup 会将三个文件打包为一个文件。如图:
![](https://img-blog.csdnimg.cn/img_convert/58d0482da54ef2fca814a394754550c8.png)
备注:如果你需要导入 CommonJS, Rollup 可以通过插件 [rollup-plugin-commonjs](rollup/rollup-plugin-commonjs) 导入已存在的 CommonJS 模块。
三、如何使用 Rollup
上文的示例中,已经引入了一些 Rollup 的配置,接下来我们简单介绍一下 Rollup 的使用方法。更多细节,可以参考官方文档。
- [Rollup英文文档](rollup.js)
- [Rollup中文翻译](rollup文档翻译 中文文档 - 前端这两年(2016~) - SegmentFault)
3.1. 安装
你现在可以运行 rollup 命令。来试试!
输出很多相关 Rollup 的命令指引,类似效果 rollup --help 或 rollup -h。
![](https://img-blog.csdnimg.cn/img_convert/36951fb647d23ea736f5af494be8f974.png)
3.2. Rollup 使用方法(命令行工具 / javascript API / 其他构建工具当插件引用)
Rollup 提供了多种打包方式,通过 format 属性可以设置你想要打包成的代码类型:
- amd - 输出成AMD模块规则,RequireJS可以用
- cjs - CommonJS规则,适合Node,Browserify,Webpack 等
- es - 默认值,不改变代码
- iife - 输出自执行函数,最适合导入html中的script标签,且代码更小
- umd - 通用模式,amd, cjs, iife都能用
Rollup 官方文档提供了 ES6 模块使用 Rollup 打包之后编译为 AMD, CommonJS, UMD 等运行示例,官网右上角 导航栏里 REL。
3.2.1. 最简单的方式——命令行工具
假设应用程序入口起点的名称为 main.js,并且你想要所有 import 的依赖(all imports)都编译到一个名为 bundle.js 的单个文件中
1) 针对浏览器
![](https://img-blog.csdnimg.cn/img_convert/f6f188f7e65e40e9c18b318318828a72.png)
2)针对 Node.js
3)针对浏览器和Node.js
![](https://img-blog.csdnimg.cn/img_convert/311c055c9cb3b06c1c27266ea6d2b636.png)
3.2.2. javascript API —— 将 Rollup 当作一个对象导出
![](https://img-blog.csdnimg.cn/img_convert/a411390d9afea13869e9e14adf627db4.webp?x-oss-process=image/format,png)
3.2.3. Rollup 与其他构建工具配合使用
链接:github.com/rollup/rollup/wiki/Build-tools
四、 Rollup 插件列表
链接:github.com/rollup/rollup/wiki/Plugins
五、参考文章:
Rollup GitHub: github.com/rollup/rollup
Rollup GitHub Wiki: rollup/wiki
Rollup 文档:rollupjs.org/