Rollup是什么

Rollup的官方文档看完,我的第一反应是?what? So? 这到底有什么用?这些事情Webpack不都已经做了吗?(webpack2 增加了tree shaking,tree shaking概念其实是Rollup提出的,所以其实Rollup出来的时候,可能写与webpack的区别还能多写好几百字)

Rollup是什么?它也是模块打包工具,类似于webpack。

安装

1
$ npm install --global rollup   #全局安装
$ npm install --save-dev rollup  #or `npm i -D rollup` 项目级别安装

—save-dev说明它与webpack一样只在项目开发,构建阶段使用。不是线上跑的项目所必需的。

配置 rollup.config.js

与webpack一样,rollup可以有配置文件,也没有不用配置文件,直接使用命令行CLI还执行也是可以的。

1
$ rollup main.js --format cjs

—format 表示我们需要把main.js按照什么标准来执行,这里—format cjs表示用CommonJS. 因为这个命令没有指定目标文件。所以会在控制台直接把main.js打包成CommonJS的标准打印出来。

回到配置文件上,rollup的配置文件如下:

1
2
3
4
5
export default {
entry : 'src/main.js',
format : 'cjs',
dest : 'bundle.js'
}

运行配置文件:

1
$ rollup -c   # rollup --config  打包的文件会输出到bundle.js
$ rollup -c -o bundle-2.js   #可以替换config中的输出文件配置,表示输出到bundle-2.js中

因为是rollup运行config.js文件,所以我们可以使用export default这种表示方法,而不需要引入类似Babel这样的东西。所以你可以在配置文件使用你的Node运行支持的es2015的特性

可以配置不同的rollup的配置文件,比如开发环境的,生产环境的。

1
$ rollup --config rollup.config.dev.js
$ rollup --config rollup.config.prod.js

配置package.json

与webpack一样,可以通过在package.json中配置scripts脚本最后通过npm来执行。

1
2
3
4
5
6
7
8
9
{
...,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c",
"dev": "rollup -c -w"
},
...
}

配置插件plugins

官方文档中介绍了几个插件rollup-plugin-json, rollup-plugin-node-resolve,rollup-plugin-babel。主要说下rollup-plugin-node-resolve。这个插件让rollup认识外部的modules。也就是说,如果不加这个插件,在js文件中如果引用node_modules中的插件, rollup是不认识的。例如:

1
$ npm install --save the-answer # or `npm i -S the-answer`

安装了 the-answer组件,然后在js文件中引用。

1
2
3
4
5
import answer from 'the-answer';

export default function(){
console.log('the answer is ' + answer);
}
1
$ npm run build

rollup会给出一个warning.

‘the-answer’ is imported by src/main.js, but could not be resolved - treating

如果要认识这些外部的组件,就需要引入plugin组件。在配置rollup.config.js中增加这样的配置

1
2
3
4
5
6
7
8
9
//rollup.config.js
import resolve from 'rollup-plugin-node-resolve';

export default {
entry : 'src/main.js',
format : 'cjs',
plugins : [ resolve() ],
dest : 'bundle.js'
};

这样,运行npm run build 就不会有报错啦~

一个完整的rollup打包的例子

1
2
3
4
5
6
rollup-demo
> src
foo.js
main.js
bundle.js
rollup.config.js

上面没有带package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/foo.js
// This function isn't used anywhere
export function square(x) {
return x * x;
}
// This function gets included
export function cube(x) {
return x * x * x;
}

// src/main.js
import {cube} from './foo.js';
console.log(cube(5)); // 125

// rollup.config.js
export default {
entry: 'src/main.js',
format: 'cjs',
dest: 'bundle.js' // equivalent to --output
};

运行rollup -c 打包出来以后,bundle.js。可以看到bundle.js中对于import没有引用的代码是没有打包进去的。

1
2
3
4
5
6
7
'use strict';
// This function isn't used anywhere
// This function gets included
function cube(x) {
return x * x * x;
}
console.log(cube(5)); // 125

到这里是不是都觉得rollup除了打包出来的代码简单,可以理解以外,好像没有什么东西了,连node_modules中的组件都还要引入一个插件才能理解。所以看官方文档不如看这篇文章Tree-shaking versus dead code elimination,这篇文章中不仅解释了tree shaking ,还对rollup进行了很多解释。其中我觉得最有意义的就是:

  • Rollup不完美,最好的结果也许是这样的步骤,例如 Rollup -> UglifyJS / 带Uglify插件的Webpack 2 (这也是我为什么觉得如果说webpack做了1,2,3个事情的话,Rollup就做了事情1)
  • Rollup的目标是生产最有效(看起来就像人写的一样)的bundle, Tree shaking 只是其中的一部分,Rollup还做了很多事(准确的说,是没有做)——没在函数中加入modules,没有把module的加载器引入到bundle的最顶部,尽量保持原代码。因为这些,所以如果是写库,用Rollup是一个很好的选择(当然Rollup也可以为apps使用,虽然Webpack比Rollupd多了很多特性,但是YMMV——选择一种新的方法也许会有意外收获哦,特别是对那些基本没有非ES6依赖的app)

所以你会考虑用Rollup吗?