Rollup
Rollup 是一款 ES Modules 打包器。它也可以将项目中散落的细小模块打包为整块代码,从而使得这些划分的模块可以更好地运行在浏览器环境或者 Node.js 环境。
从作用上来看,Rollup 与 Webpack 非常类似。不过相比于 Webpack,Rollup 要小巧的多。因为 Webpack 在配合一些插件的使用下,几乎可以完成开发过程中绝大多数前端工程化的工作。而 Rollup 可以说仅仅是一个 ES Modules 打包器,没有更多其他的功能了。
例如,在 Webpack 中支持 HMR 这种对开发过程十分友好的功能,而在 Rollup 中就没有办法完全支持。
Rollup 诞生的目的并不是要与 Webpack 这样的工具全面竞争。它的初衷只是希望能够提供一个高效的 ES Modules 打包器,充分利用 ES Modules 的各项特性,构建出结构扁平,性能出众的类库。
Rollup 的优势:
- 输出结果更加扁平,执行效率更高;
- 自动移除未引用代码;
- 打包结果依然完全可读。
Rollup的缺点:
- 加载非 ESM 的第三方模块比较复杂;
- 因为模块最终都被打包到全局中,所以无法实现 HMR;
- 浏览器环境中,代码拆分功能必须使用 Require.js 这样的 AMD 库。
基本使用
安装
通过 npm 安装 rollup 这个模块。具体命令如下:
$ npm i rollup --save-dev
安装完成过后,rollup 这个模块同样会在 node_modules/.bin 目录中为我们提供一个 CLI 程序,我们就可以通过这个 CLI 去使用 Rollup 打包。具体命令如下:
$ npx rollup
执行 rollup 命令,在不传递任何参数的情况下,这个命令会自动打印出它的帮助信息。
配置文件
Rollup 同样支持以配置文件的方式去配置打包过程中的各项参数,我们可以在项目的根目录下新建一个 rollup.config.js 的配置文件。
// ./rollup.config.js
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'es' // 输出格式
}
}
这个文件中需要导出一个配置对象,在这个对象中我们可以通过 input 属性指定打包的入口文件路径,通过 output 指定输出相关配置,output 属性是一个对象,在 output 对象中可以使用 file 属性指定输出的文件名,format 属性指定输出代码的格式。
完成以后,我们回到命令行,再次执行 rollup 命令,不过需要注意的是,这里需要通过 --config 参数来表明使用项目中的配置文件。你也可以通过这个参数来指定不同的配置文件名称。具体命令如下:
$ npx rollup --config # 使用默认配置文件
$ npx rollup --config rollup.prod.js # 指定配置文件路径
输出格式
Rollup 打包支持多种输出格式,这里我们回到配置文件中,配置同时输出所有格式下的文件,具体配置如下:
// ./rollup.config.js
// 所有 Rollup 支持的格式
const formats = ['es', 'amd', 'cjs', 'iife', 'umd', 'system']
export default formats.map(format => ({
input: 'src/index.js',
output: {
file: `dist/bundle.${format}.js`,
format
}
}))
在这个配置当中我们导出了一个数组,数组中的每个成员都是一个单独的打包配置,这样 Rollup 就会分别按照每个配置单独打包。
使用插件
Rollup 自身的功能就只是 ES Modules 模块的合并,如果有更高级的要求,例如加载其他类型的资源文件或者支持导入 CommonJS 模块,又或是编译 ES 新特性,这些额外的需求 Rollup 同样支持使用插件去扩展实现。
Webpack 中划分了 Loader、Plugin 和 Minimizer 三种扩展方式,而插件是 Rollup 的唯一的扩展方式。
例如我们使用一个可以让我们在代码中导入 JSON 文件的插件@rollup/plugin-json,首先我们需要将 @rollup/plugin-json 作为项目的开发依赖安装进来。具体安装命令:
$ npm i @rollup/plugin-json --save-dev
安装完成过后,我们打开配置文件。由于 rollup 的配置文件中可以直接使用 ES Modules,所以我们这里使用 import 导入这个插件模块。具体代码如下:
// ./rollup.config.js
import json from '@rollup/plugin-json'
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'es'
},
plugins: [
json()
]
}
@rollup/plugin-json 模块的默认导出就是一个插件函数。我们可以将这个函数的调用结果添加到配置对象的 plugins 数组中,注意这里是将调用结果放到数组中,而不是将这个函数直接放进去。
加载 NPM 模块
Rollup 默认只能够按照文件路径的方式加载本地的模块文件,对于 node_modules 目录中的第三方模块,并不能像 Webpack 一样,直接通过模块名称直接导入。
为了抹平这个差异,Rollup 给出了一个 @rollup/plugin-node-resolve 插件,通过使用这个插件,我们就可以在代码中直接使用模块名称导入模块了。
同样,我们需要先安装这个插件,具体命令如下:
$ npm i @rollup/plugin-node-resolve --save-dev
安装完成过后,打开配置文件,这里同样导入插件函数,然后把它配置到 plugins 数组中。具体配置如下:
// ./rollup.config.js
import json from '@rollup/plugin-json'
import resolve from '@rollup/plugin-node-resolve'
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'es'
},
plugins: [
json(),
resolve()
]
}
完成以后我们就可以回到代码中直接导入 node_modules 中的第三方模块了。例如:
// ./src/index.js
import { camelCase } from 'lodash-es'
console.log(camelCase('hello rollup'))
这里我导入的是我提前安装好的一个 lodash-es 模块,这个模块就是常用的 lodash 模块的 ESM 版本。导入过后我们就可以使用这个模块所提供的工具方法了。
这里使用 Lodash 的 ESM 版本而不是 Lodash 普通版本的原因是 Rollup 默认只能处理 ESM 模块。如果要使用普通版本则需要额外处理。
加载 CommonJS 模块
由于 Rollup 设计的是只处理 ES Modules 模块的打包,所以如果在代码中导入 CommonJS 模块,默认是不被支持的。但是目前大量的 NPM 模块还是使用 CommonJS 方式导出成员,所以为了兼容这些模块。官方给出了一个插件,叫作 @rollup/plugin-commonjs。
这里我添加了一个 cjs-module.js 文件,具体代码如下:
// ./src/cjs-module.js
module.exports = {
foo: 'bar'
}
这个文件中使用 CommonJS 的方式导出了一个对象。然后回到入口文件中通过 ES Modules 的方式导入,具体代码如下:
// ./src/index.js
// 导入 CommonJS 模块成员
import cjs from './cjs-module'
// 使用模块成员
console.log(cjs) // cjs => { foo: 'bar' }
入口文件导入的结果就是 cjs-module.js 中导出的对象了。
Code Splitting
Rollup 的最新版本中已经开始支持代码拆分了。我们同样可以使用符合 ES Modules 标准的动态导入方式实现模块的按需加载。例如:
// ./src/index.js
// 动态导入的模块会自动分包
import('./logger').then(({ log }) => {
log('code splitting~')
})
Rollup 内部也会处理代码拆分。在 Rollup 在分包过后会输出多个 JS 文件,需要我们在配置中指定输出的目录,而不是一个具体的文件名,具体配置如下:
// ./rollup.config.js
export default {
input: 'src/index.js',
output: {
// file: 'dist/bundle.js', // code splitting 输出的是多个文件
dir: 'dist',
format: 'es'
}
}
这里我们将 output 配置中的 file 选项删掉,取而代之的是添加一个 dir 选项,把它设置为 dist,也就是输出到 dist 目录中。
常用插件
- rollup-plugin-cleanup:用于删除注释、修剪尾随空格、压缩空行以及规范化 JavaScript 文件中的行结尾
- @rollup/plugin-commonjs:rollup本身是不支持CommonJS的,使用了这个插件,就可以解析CommonJS模块了。另外如果在一个配置内同时使用了@rollup/plugin-babel,需要把@rollup/plugin-commonjs 插件放在前面使用。
- rollup-plugin-filesize:在 cli 中显示文件大小的汇总插件
- @rollup/plugin-json:可以将.json文件转为es6模块供rollup处理。
- @rollup/plugin-node-resolve:一个使用节点解析算法定位模块的 Rollup 插件,用于在中使用第三方模块node_modules
- rollup-plugin-progress:显示汇总打包程序正在转译的当前模块
- @rollup/plugin-replace:在打包时替换文件中的目标字符串
- @rollup/plugin-strip:用于从代码中删除debugger类似的语句和函数assert.equal和console.log
- @rollup/plugin-terser:用于在生产环境中,对代码进行压缩
- rollup-plugin-typescript2:包含编译器错误的typescript的汇总插件,这个版本比原始版本稍慢,但它将打印出typescript语法和语义诊断消息(毕竟使用typescript的主要原因)。
- rollup-plugin-dts:自动帮你生成类型声明文件
*.d.ts
- @rollup/plugin-babel:把最新的语法转为es5
- rollup-plugin-visualizer:可视化并分析你的 Rollup 包,看看哪些模块占用了空间。
- rollup-plugin-clear:打包资源时清除特定目录
rollup打包ts项目
安装rollup和TypeScript相关依赖:
npm i -D rollup typescript tslib rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-typescript2 rollup-plugin-cleanup
TIP
tslib这个依赖库也是必需的,因为rollup-plugin-typescript2插件依赖了该库。