向来缘浅 奈何情深
既然琴瑟起 何以笙箫默顾漫《何以笙箫默》
Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。
源码仓库:https://github.com/carolyicheng666/rollup-study,欢迎Star
下面先进行一些准备工作,先把源码拷贝一份到自己的本机上:
1
$ git clone https://github.com/carolyicheng666/rollup-study.git
然后下载所依赖的库文件:
1
$ npm i
我源码的 rollup 版本是 0.56.5,如果版本有更新,可能存在写法上的差异,建议到rollup官网查询。
demo01: 输出包的格式
一般分为五种:
amd – 异步模块定义,用于像RequireJS这样的模块加载器
cjs – CommonJS,适用于 Node 和 Browserify/Webpack
es – 将软件包保存为ES模块文件
iife – 一个自动执行的功能,适合作为<script>
标签。(如果要为应用程序创建一个捆绑包,您可能想要使用它,因为它会使文件大小变小。)
umd
– 通用模块定义,以amd,cjs 和 iife 为一体
如果没有设置,会报下列错误:
1
[!] Error: You must specify options.format, which can be one of 'amd', 'cjs', 'es', 'iife' or 'umd'
命令行执行是 rollup -i 入口文件 -f 输出包格式 -o 输出文件
,如果是 iife 和 umd 格式,还需要加 -n 输出的包名
。更多的配置请点击这里
我们简单配置一下 package.json
:
1
2
3
4
5
6
7
8"scripts": {
"build:amd": "rollup index.js -f amd -o ./dist/dist.amd.js",
"build:cjs": "rollup index.js -f cjs -o ./dist/dist.cjs.js",
"build:es": "rollup index.js -f es -o ./dist/dist.es.js",
"build:iife": "rollup index.js -f iife -n result -o ./dist/dist.iife.js",
"build:umd": "rollup index.js -f umd -n result -o ./dist/dist.umd.js",
"build:all": "npm run build:amd && npm run build:cjs && npm run build:es && npm run build:iife && npm run build:umd"
}
执行命令即可:
1
$ npm run build:all
demo02: 使用配置文件 rollup.config.js
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
34
35
36
37
38
39export default {
// 核心选项
input, // 必须
external,
plugins,
// 额外选项
onwarn,
// danger zone
acorn,
context,
moduleContext,
legacy
output: { // 必须 (如果要输出多个,可以是一个数组)
// 核心选项
file, // 必须
format, // 必须
name,
globals,
// 额外选项
paths,
banner,
footer,
intro,
outro,
sourcemap,
sourcemapFile,
interop,
// 高危选项
exports,
amd,
indent
strict
},
};
本例中只设置了必须的选项,其它一些常用的选项会在后面的例子中看到。
如果使用了配置文件,那么命令行运行的命令就是 rollup -c
,我们在 package.json
中设置一下:
1
2
3"scripts": {
"build": "rollup -c"
}
这时候就可以运行命令
1
$ npm run build
demo03: 实时监听
每一次改动都要运行一次命令实在是太麻烦了,所以,几乎每一种工具都会有实时监听的设置,rollup也不例外,在命令后加上 -w
即可
1
2
3"scripts": {
"dev": "rollup -c -w"
}
运行命令实现实时监听
1
$ npm run dev
demo04: 集成 npm packages
需要用到两个插件:rollup-plugin-node-resolve
和 rollup-plugin-commonjs
rollup-plugin-node-resolve
插件可以告诉 Rollup 如何查找外部模块
一些库导出成你可以正常导入的ES6模块 - the-answer 就是一个这样的模块。 但是目前,npm中的大多数包都是以CommonJS模块的形式出现的。 在它们更改之前,我们需要将CommonJS模块转换为 ES2015 供 Rollup 处理。rollup-plugin-commonjs
插件就是用来将 CommonJS 转换成 ES2015 模块的。
rollup.config.js
配置:
1
2
3
4
5
6
7
8
9
10
11import commonjs from 'rollup-plugin-commonjs';
import resolve from 'rollup-plugin-node-resolve';
export default {
input: 'index.js',
output: {
format: 'cjs',
file: './dist/dist.js'
},
plugins: [ resolve(), commonjs() ]
}
demo05:Peer dependencies
假如我们引入了 the-answer
和 lodash
这两个模块, Rollup 默认会把他们打包在一起,那么这样打包出来的文件就会很大,因此我们希望 lodash
变成外部引用,这是可以做到的,设置 external
选项即可,这个选项接收一个数组,代表所有需要外部引入的模块,此数组不能处理通配符。
本例中可以这样设置:
1
external: ['lodash']
demo06: Babel
使用 Babel 和 Rollup 的最简单方法是使用 rollup-plugin-babel
和其它工具一样,先要创建 .babelrc
文件:
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{
"presets": [
["env", {
"modules": false
}]
],
"plugins": [
"external-helpers"
]
}
```
这里我们需要 `babel-preset-env` 和 `babel-plugin-external-helpers` 这两个插件,为什么不用 ES2015 而用 env,可以看看[这篇文章](http://babeljs.io/env/)。而 `external-helpers` 插件,它允许 Rollup 在包的顶部只引用一次 “helpers”,而不是每个使用它们的模块中都引用一遍,大家可以对比一下引入这个插件和不引入打包后生成的文件的区别。
``` javascript
import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
},
plugins: [
resolve(),
babel({
exclude: 'node_modules/**' // 只编译我们的源代码
})
]
};
demo07: CDN 引入
比如我们想使用 CDN 方式引入 jquery
,那么在 output
的 path
选项添加即可
1
2
3
4
5
6
7output: {
...
paths: {
jquery: 'https://cdn.bootcss.com/jquery/3.2.1/jquery.js'
},
...
}
demo08: 集成 Gulp
Rollup 返回 gulp 能明白的 promises,所以集成是很容易的。
gulpfile.js
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const gulp = require('gulp');
const rollup = require('rollup');
const resolve = require('rollup-plugin-node-resolve');
const babel = require('rollup-plugin-babel');
gulp.task('build', () => {
return rollup.rollup({
input: './index.js',
plugins: [
resolve(),
babel({
exclude: 'node_modules/**'
})
]
}).then(bundle => {
return bundle.write({
file: './dist/dist.js',
format: 'umd',
name: 'dist',
sourcemap: true
});
});
});
也可以用 async/await
语法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const gulp = require('gulp');
const rollup = require('rollup');
const resolve = require('rollup-plugin-node-resolve');
const babel = require('rollup-plugin-babel');
gulp.task('build', async function () {
const bundle = await rollup.rollup({
input: './index.js',
plugins: [
resolve(),
babel({
exclude: 'node_modules/**'
})
]
});
await bundle.write({
file: './dist/dist.js',
format: 'umd',
name: 'dist',
sourcemap: true
});
});
demo09: 添加 banner/footer
可以在输出文件的头部添加 banner 和尾部添加 footer 注释信息,例如:
1
2
3
4
5
6import pkg from './package.json';
export default {
...
banner: '/* dist version ' + pkg.version + ' */',
footer: '/* follow me on Github! @' + pkg.author + ' */'
}
demo10: 使用插件
rollup的插件有很多,这里是插件列表,稍微看看配置就能上手。
比如我们使用rollup-plugin-json插件解析 json 文件:main.js
:
1
2
3
4
5
6import answer from 'the-answer';
import pkg from './package.json';
export default function () {
console.log('the answer is ' + answer + ', the version is ' + pkg.version);
}
rollup.config.js
:
1
2
3
4
5import json from 'rollup-plugin-json';
export default {
...
plugins: [ json() ]
}
再比如我们使用rollup-plugin-uglify压缩输出文件:rollup.config.js
:
1
2
3
4
5import uglify from 'rollup-plugin-uglify';
export default {
...
plugins: [ uglify() ]
}
demo11: 引入 sass 文件
rollup 不仅能打包 js,还能打包 css 或者 css 的预处理文件 sass,less,stylus等。就拿 sass 举例,我们需要引入 rollup-plugin-scss 插件rollup.config.js
:
1
2
3
4
5
6
7
8
9
10import scss from 'rollup-plugin-scss';
export default {
...
plugins: [
scss({
output: './dist/test.css'
})
]
}
index.js
:
1
2import './main.scss';
...
想打包其它文件也可以去上面的插件列表中查找,相信大家会有更多的收获
demo12: 开发环境和生产环境
与其它打包工具一样,rollup 也能设置开发环境和生产环境(这一点其实和rollup没啥关系,还是nodejs的功劳)
简单配置一下(只有压缩和不压缩的区别,哈哈):package.json
:
1
2
3
4
5
6...
"scripts": {
"dev": "rollup -c --environment NODE_ENV:development",
"build": "rollup -c --environment NODE_ENV:production"
}
...
rollup.config.js
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import resolve from 'rollup-plugin-node-resolve';
import json from 'rollup-plugin-json';
import uglify from 'rollup-plugin-uglify';
const base = [resolve(), json()];
const dev = [];
const prod = [uglify()];
let isProd = process.env.NODE_ENV === 'production';
let plugins = [...base].concat(isProd ? prod : dev);
export default {
input: 'index.js',
output: {
file: './dist/dist.js',
format: 'cjs',
name: 'dist',
sourcemap: isProd
},
plugins: plugins
}
开发环境: npm run dev
生产环境: npm run build
Rollup VS Webpack
用过这两个工具的朋友一定会有这种疑问,这两个工具非常类似,有感觉有一点点不同,那么到底什么时候用什么比较好呢?我找到了一篇文章,大家可以参考参考,传送门