Rollup 是一个 JavaScript 模块打包器,它能将多个小的、分散的 js 文件合并压缩成一个大的 js 文件,以供其他项目引入使用。

它有自己的应用场景,Rollup 更适合用来生成 lib 库,而 Webpack 和 Browserify 更适合用来生成应用项目。

特点

Rollup 对代码模块使用新的 ES6 标准化格式,也就是说使用 import/export 来处理代码模块,至于模块文件内部使用使用 ES6 语法或者是 ES6 的 API,不作规定和要求,如果使用,见后续引入 babel 处理器即可。

所以,使用 Rollup 处理的代码模块最好都要是 ES6 标准化的模块(使用 import/export),因为其可以对模块文件进行静态分析,并将排除任何未实际使用的代码,即所谓的「Tree-Shaking」。

为了保证 Rollup 最终打包的代码模块都符合 ES6 模块标准,对于自己的写的文件那就严格统一使用 import/export,并且对于要使用 babel 工具进行语法编译的,需要在 .babelrc 配置文件中的 modules 一项设置为 false,也就是不转换模块(因为其默认值为 commonjs,即会默认转成 commonjs 格式文件)。

而对于第三方的 commonjs 格式的模块文件,我们可以借助 rollup-plugin-commonjs 插件,来将其转换为 es 模块;前提还需要安装和引入 rollup-plugin-node-resolve 插件,原因是 Rollup 不同于 Webpack 和 Browserify,它不知道如何处理模块中的依赖,所以 rollup-plugin-node-resolve 插件可以告诉 Rollup 如何查找外部模块。

请注意,目前大部分的 npm 包都是以 commonjs 模块形式出现的,所以以防万一,还是安装和引入该插件 rollup-plugin-commonjs 吧。另外,为了防止其他插件的改变破坏 commonjs 的检测,rollup-plugin-commonjs 应该用在其他插件转换模块之前。具体看后面的配置文件。

1. 快速开始

安装 rollup:

1
2
3
4
5
6
7
$ npm install --global rollup

# 查看版本号
$ rollup --version

# 查看可用参数
$ rollup --help

打包代码成 lib:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 生成在浏览器使用
$ rollup ./src/main.js --file ./dist/bundle.js --format iife

# 生成在 node 环境使用
$ rollup ./src/main.js --file ./dist/bundle.js --format cjs

# 生成均可在浏览器和 node 环境使用
$ rollup ./src/main.js --file ./dist/bundle.js --format umd --name "mylib"

# 生成 es 模块文件
$ rollup ./src/main.js --file ./dist/bundle.js --format es

# 生成异步模块,适用于 RequireJS 类的加载器
$ rollup ./src/main.js --file ./dist/bundle.js --format amd

2. 使用配置文件创建第一个 lib

如上可见,如果我们使用命令行来打包生成 lib,会很复杂,而且需要记忆,不能重复使用,为了解决这几个痛点,我们使用 npm scripts 和 Rollup 项目配置文件 rollup.config.js 来打包生成lib。

首先在根目录下创建一个 package.json,然后填入必要的信息,这是前端工程师的基本素养和能力,因此过程省略。

其次,安装两个必要调试依赖:

1
2
$ npm install --save-dev rollup-plugin-node-resolve
$ npm install --save-dev rollup-plugin-commonjs

当然了,如果没有依赖第三方的 npm 库,以上两个都不用安装。

第三,安装 babel 相关依赖,为了让我们能够在项目中更加骚气地使用 ecmascript:

1
2
3
4
5
# 如果使用 babel@7
$ npm install --save-dev @babel/core
$ npm install --save-dev @babel/preset-env
$ npm install --save-dev @babel/plugin-transform-runtime
$ npm install --save-dev rollup-plugin-babel

第四,根目录下创建 babel 的项目配置文件 .babelrc 并填入:

1
2
3
4
5
6
7
8
{
"presets": [
[ "@babel/env", { "modules": false } ]
],
"plugins": [
"@babel/plugin-transform-runtime"
]
}

第五,根目录下创建 rollup 配置文件 rollup.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// rollup.config.js
import nodeResolve from 'rollup-plugin-node-resolve';
import converCjsToEs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';

export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
// 使用 umd 格式,则必须提供 name 选项
name: 'myLib',
format: 'umd'
},
plugins: [
nodeResolve(),
converCjsToEs(),
babel({
// 只编译我们的源代码
exclude: 'node_modules/**',
// 如果使用了 @babel/plugin-transform-runtime
// 就必须开启该选项
runtimeHelpers: true,
}),
]
};

第六,在 package.json 中添加 script:

1
2
3
4
{
"scripts": {
"build": "rollup --config ./rollup.config.js"
}

3. 声明引用外部模块,但不打包

Rollup 也可以像 Webpack 一样使用 external 来声明将哪些模块视为「外部模块」,即 peerDependencies,这样在打包的时候,就不会将这些模块打包进去,但是要注意,在应用工程中需要你手动去安装这些外部模块。

假设我们需要用到 lodash 作为外部模块引用:

1
2
3
4
// src/main.js
import _ from 'lodash';

// ...

那么需要在 rollup 的配置文件 rollup.config.js 中声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// rollup.config.js
import nodeResolve from 'rollup-plugin-node-resolve';
import converCjsToEs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';

export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
// 使用 umd 格式,则必须提供 name 选项
name: 'myLib',
format: 'umd'
},
plugins: [
nodeResolve(),
converCjsToEs(),
babel({
// 只编译我们的源代码
exclude: 'node_modules/**',
// 如果使用了 @babel/plugin-transform-runtime
// 就必须开启该选项
runtimeHelpers: true,
}),
],
/**
* ******************
* 声明外部依赖
* ******************
*/
extenal: [
'lodash'
]
};

4. 扩展你想要的功能

尽在 https://github.com/rollup/awesome