核心概念
同webpack一样,rollup也有以下几大核心概念:
- input:入口文件,类比于webpack的entry,它指明了我们库文件入口位置。
- output:输出位置,它指明了打包后的输出信息,包括:输出目录,打包文件名等。
- plugins:插件,rollup在构建过程中,插件可提供一些辅助功能,例如:alias别名解析、转义ES6等。
- external:当我们的库依赖于其它第三方库时,我们不需要把这些第三方库一起打包,而是应该把依赖写在external里面。
- rollup同样适合使用配置文件的做法来配置打包的选项,例如:
// rollup.config.js
export default {
input: 'src/main.js',
output: [
{ file: 'dist/vue.js', format: 'umd', name: 'Vue' },
{ file: 'dist/vue.common.js', format: 'cjs', name: 'Vue' },
{ file: 'dist/vue.esm.js', format: 'es', name: 'Vue' }
],
...
}
构建说明:
- umd:此选项构建出来的库文件是一个通用模式,可以通过不同的方式去使用:script标签引入,ES Module规范引入和CommonJs规范引入等。
- cjs: 此选项构建出来的库文件主要为CommonJs规范,可在Node环境中使用。
- es:此版本构建出来的库文件主要为ES Module规范,可在支持ES Module也就是import/export的环境中使用。
有了以上配置文件,我们可以在package.json中配置打包命令:
{
"scripts": {
"dev": "rollup -w -c rollup.config.js"
}
}
参数说明:
- -c:为--config的缩写,表示设置rollup打包的配置。
- -w:为--watch的缩写,在本地开发环境添加-w参数可以监控源文件的变化,自动重新打包。
常用插件
rollup并不像webpack那样强大,它需要和其它插件配合使用才能完成特定的功能,常用的插件有:
- @rollup/plugin-commonjs:将CommonJs规范的模块转换为ESM规范,提供rollup使用。
- @rollup/plugin-node-resolve:与@rollup/plugin-commonjs插件一起使用,配合以后就可以使用node_modules下的第三方模块代码了。
- @rollup/plugin-babel:把ES6代码转义成ES5代码,需要同时安装@babel/core和@babel/preset-env插件。注意:如果使用了高于ES6标准的语法,例如async/await,则需要进行额外的配置。
- rollup-plugin-terser:代码压缩插件,另外一种方案是rollup-plugin-uglify + uglify-es进行代码压缩,不过更推荐第一种方案。
- @rollup/plugin-json: 支持从.json读取信息,配合rollup的Tree Shaking可只打包.json文件中我们真正用到的部分。
以上插件使用案例如下:
// rollup.config.js
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import babel from '@rollup/plugin-babel'
import json from '@rollup/plugin-json'
import { terser } from 'rollup-plugin-terser'
const config = {
input: 'src/index.js',
output: [
{ file: 'dist/vue.js', format: 'umd', name: 'Vue' },
{ file: 'dist/vue.common.js', format: 'cjs', name: 'Vue', exports: 'auto' },
{ file: 'dist/vue.esm.js', format: 'es', name: 'Vue', exports: 'auto' }
],
plugins: [
commonjs(),
resolve(),
babel(),
terser(),
json()
]
}
export default config
当我们使用打包命令进行打包时,会在dist目录下生成三个文件,分别是vue.js、vue.common.s以及vue.esm.js。
配置案例
在介绍配置案例之前,我们需要新建一个项目,并且创建一些必要的文件目录,如下:
|-- rollup-learn
| |-- src
| | |-- index.js # 入口文件
然后使用如下命令创建一个package.json文件
npm init -y
创建完毕后,再修改package.json,修改后如下:
{
"name": "rollup-learn",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "rollup -w -c rollup.config.js",
"build": "rollup -c rollup.config.js"
},
"keywords": [],
"author": "wangtunan",
"license": "MIT"
}
这样,我们的基础目录已经有了,在之后的小节中,所有案例均基于这个基础的目录结构。
基础配置
根据之前的章节,我们需要安装一些npm包,如下:
# 安装rollup核心包
$ npm install rollup -D
# 安装rollup插件包
$ npm install @rollup/plugin-commonjs @rollup/plugin-node-resolve -D
随后,根目录新建rollup.config.js,并撰写如下内容:
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
export default {
input: 'src/index.js',
output: [
{ file: 'dist/vue.js', format: 'umd', name: 'Vue' },
{ file: 'dist/vue.common.js', format: 'cjs', name: 'Vue', exports: 'auto' },
{ file: 'dist/vue.esm.js', format: 'es', name: 'Vue' },
],
plugins: [
commonjs(),
resolve()
]
}
然后,我们需要在入口文件撰写一些内容:
export function add (a, b) {
return a + b
}
export function minus (a, b) {
return a - b
}
最后,运行我们在package.json文件中定义的build命令:
npm run build
运行完毕后,会在dist目录下生成三个文件,此时的文件目录结构如下:
|-- rollup-learn
| |-- dist
| | |-- vue.js
| | |-- vue.common.js
| | |-- vue.esm.js
| |-- src
| | |-- index.js
| |-- rollup.config.js
| |-- package.json
我们以vue.esm.js文件为例,其打包后的文件代码如下:
function add (a, b) {
return a + b
}
function minus (a, b) {
return a - b
}
export { add, minus };
为了让我们rollup打包出来的库,能够支持commonjs和esm这两种方式引入,我们需要修改一下package.json,改动如下:
{
// ... 省略其它
"main": "dist/vue.commin.js",
"module": "dist/vue.esm.js",
// ... 省略其它
}
支持ES6转义
为了让库文件具有更好的兼容性,需要把ES6代码在打包的时候转义成ES5。
要做到这一步,需要我们安装几个npm包,如下:
# 安装rollup插件包
$ npm install @rollup/plugin-babel -D
# 安装babel相关包
$ npm install @babel/core @babel/preset-env -D
安装完以上npm包后,需要在rollup.config.js中使用babel插件,如下:
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import babel from '@rollup/plugin-babel'
export default {
input: 'src/index.js',
output: [
{ file: 'dist/vue.js', format: 'umd', name: 'Vue' },
{ file: 'dist/vue.common.js', format: 'cjs', name: 'Vue', exports: 'auto' },
{ file: 'dist/vue.esm.js', format: 'es', name: 'Vue' },
],
plugins: [
commonjs(),
resolve(),
babel()
]
}
然后,需要在根目录下新建.babelrc文件,并撰写如下内容:
{
"presets": [
"@babel/preset-env"
]
}
为了测试是否正确的处理了ES6相关的代码,我们需要改动一下入口文件index.js:
export const add = (a, b) => {
return a + b
}
export const minus = (a, b) => {
return a - b
}
最后,我们再次运行npm run build打包命令,查看dist目录下vue.esm.js文件打包后的代码。
var add = function add(a, b) {
return a + b;
};
var minus = function minus(a, b) {
return a - b;
};
export { add, minus };
可以看到,ES6相关的代码已经被正确的转义了。
支持区分开发环境和生产环境
在Rollup中,区分开发环境和生产环境配置十分简单,可以使用不同的配置文件来进行区分
我们规定rollup.dev.config.js为开发环境的配置,rollup.prod.config.js为生产环境的配置,rollup.base.config.js为公共配置。
先创建这两个文件,然后添加配置代码。
rollup.base.config.js代码如下:
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import babel from '@rollup/plugin-babel'
export default {
input: 'src/index.js',
plugins: [
commonjs(),
resolve(),
babel()
]
}
rollup.dev.config.js代码如下:
import baseConfig from './rollup.base.config'
const devConfig = {
...baseConfig,
output: [
{ file: 'dist/vue.js', format: 'umd', name: 'Vue' },
{ file: 'dist/vue.common.js', format: 'cjs', name: 'Vue', exports: 'auto' },
{ file: 'dist/vue.esm.js', format: 'es', name: 'Vue' },
]
}
export default devConfig
rollup.prod.config.js代码如下:
import baseConfig from './rollup.base.config'
const prodConfig = {
...baseConfig,
output: [
{ file: 'dist/vue.min.js', format: 'umd', name: 'Vue' },
{ file: 'dist/vue.common.min.js', format: 'cjs', name: 'Vue', exports: 'auto' },
{ file: 'dist/vue.esm.min.js', format: 'es', name: 'Vue' },
]
}
export default prodConfig
配置文件改动完毕后,我们需要在package.json文件中修改打包命令:
"scripts": {
"dev": "rollup -w -c rollup.dev.config.js",
"build": "rollup -c rollup.prod.config.js"
}
我们尝试使用npm run build命令打包生产环境代码,执行后会在dist目录下生成三个.min.js文件。
此时的目录如下:
|-- rollup-learn
| |-- dist
| | |-- vue.js
| | |-- vue.min.js
| | |-- vue.common.js
| | |-- vue.common.min.js
| | |-- vue.esm.js
| | |-- vue.esm.min.js
| |-- src
| | |-- index.js
| |-- .babelrc
| |-- rollup.base.js
| |-- rollup.dev.js
| |-- rollup.prod.js
| |-- package.json
支持生产环境代码压缩
目前来说,使用npm run dev和npm run build这两个命令打包出来的文件,除了文件名有点区别,其它代码都是一样的。
现在,我们需要对生产环境进行压缩,需要先安装一个npm包。
# 安装代码压缩插件
$ npm install rollup-plugin-terser -D
插件安装完毕后,需要在rollup.prod.config.js文件中添加此插件。
import baseConfig from './rollup.base.config'
import { terser } from 'rollup-plugin-terser'
const prodConfig = {
...baseConfig,
output: [
{ file: 'dist/vue.min.js', format: 'umd', name: 'Vue' },
{ file: 'dist/vue.common.min.js', format: 'cjs', name: 'Vue', exports: 'auto' },
{ file: 'dist/vue.esm.min.js', format: 'es', name: 'Vue' },
],
plugins: [
...baseConfig.plugins,
terser()
]
}
export default prodConfig
修改完毕后,再次运行npm run build命令,查看vue.min.js中的代码,发现代码已经成功被压缩了。
支持TypeScript
如果要支持TypeScript,需要安装几个npm包,如下:
# 安装rollup插件
$ npm install rollup-plugin-typescript2 -D
# 安装ts相关包
$ npm install typescript tslib -D
安装完毕后,把入口文件后缀改为.ts,并且分别给add和minus这两个方法添加类型:
export const add = (a: number, b: number): number => {
return a + b
}
export const minus = (a: number, b: number): number => {
return a - b
}
最后,在rollup.base.config.js文件中使用rollup插件。
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import babel from '@rollup/plugin-babel'
import typescript from 'rollup-plugin-typescript2'
export default {
input: 'src/index.ts',
plugins: [
commonjs(),
resolve(),
babel(),
typescript()
]
}
再次运行npm run dev或者npm run build后,在dist目录下查看打包后的源码,可以看到已经能正确识别ts代码了。
支持Jest自动化测试
如果需要支持Jest自动化测试,需要我们安装额外的npm包:
# 安装jest
$ npm install jest -D
因为要测试的文件是包含ts代码,因此我们需要再安装其它的包:
$ npm install babel-jest ts-jest -D
安装完毕后,在根目录下新建jest.config.js文件,并填写配置:
module.exports = {
preset: 'ts-jest',
testMatch: [
"**/tests/**/*.(spec|test).(js|jsx|ts|tsx)"
],
collectCoverage: true,
coverageDirectory: '<rootDir>/tests/coverage',
collectCoverageFrom: [
'src/**/*.(js|jsx|ts|tsx)'
]
}
配置说明:
- preset:要测试的代码,包含ts的内容,使用ts-jest来处理。
- testMatch:测试哪些文件,以上配置表明我们要测试tests目录下所有.(spce|test).(js|jsx|ts|tsx)。
- collectCoverage:生成测试报告。
- coverageDirectory: 测试报告存放位置。
- collectCoverageFrom:测试报告收集范围。
配置文件撰写完毕后,我们在根目录下新建一个tests目录,并添加一个测试文件index.test.js。
// 如果需要使用import,需要自己额外的配置
const { add } = require('../src/index')
describe('index.ts', () => {
it('test add func', () => {
expect(add(1, 2)).toBe(3)
})
})
最后,需要在package.json文件中添加一条测试命令:
"scripts": {
"dev": "rollup -w -c rollup.dev.config.js",
"build": "rollup -c rollup.prod.config.js",
"test": "jest"
}
运行npm run jest命令,它会在控制台输出一些测试覆盖率的信息。
PASS tests/index.test.js
index.ts
√ test add func (2 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 83.33 | 100 | 50 | 75 |
index.ts | 83.33 | 100 | 50 | 75 | 6
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.345 s
Ran all test suites.