Rollup概述
Rollup是一款ES Moudle的打包器,作用上与Webpack非常类似,但是它更小巧,因为它仅仅是一款ESM的打包器,没有其他额外的功能。例如Rollup中并不支持类似HMR这种高级特性。
Rollup并非要与Webpack竞争,它只是提供一个充分利用ESM各项特性的高效打包器,构建出一个解构扁平,性能出众的类库。
快速上手
-
创建一个简单的demo,包含3个js文件:
message.js:export default { hi: 'Hey Guys, I am zce~' }
logger.js:
export const log = msg => { console.log('---------- INFO ----------') console.log(msg) console.log('--------------------------') } export const error = msg => { console.error('---------- ERROR ----------') console.error(msg) console.error('---------------------------') }
index.js:
// 导入模块成员 import { log } from './logger' import messages from './messages' // 使用模块成员 const msg = messages.hi log(msg)
-
安装rollup
yarn add rollup --dev
-
在命令行运行:
yarn gullup ./src/index.js --file dist/bundle.js
此时项目中多了dist文件夹,bundle.js内容如下:
const log = msg => {
console.log('---------- INFO ----------');
console.log(msg);
console.log('--------------------------');
};
var messages = {
hi: 'Hey Guys, I am zce~'
};
// 导入模块成员
// 使用模块成员
const msg = messages.hi;
log(msg);
Rollup不光帮我们打包了代码,而且将未使用的logger.js下的error给剔除掉了。即默认开启了TreeShaking功能。
Rollup配置文件
在项目根目录下添加rollup.config.js文件:
export default {
input: './src/index.js',
output: {
file: './dist/bundle.js',
formate: 'iife'
}
}
在命令行终端输入打包命令:
yarn rollup --config
也可以在命令后加指定的配置文件名来区分开发环境和生产环境的配置文件
yarn rollup --config rollup.config.js
Rollup 插件
Rollup自身的功能就是对ESM进行合并打包,如果需要更高级的功能,如加载其他类型资源模块,导入CommonJS模块,编译ES新特性,Rollup支持使用插件的方式扩展实现,插件是Rollup唯一的扩展方式。
下面通过导入json文件学习如何使用Rollup插件。
安装插件:
yarn add rollup-plugin-json --dev
在配置文件中添加json插件:
import json from 'rollup-plugin-json' // here
export default {
input: './src/index.js',
output: {
file: './dist/bundle.js',
formate: 'iife'
},
plugins: [
json() // here
]
}
./src/index.js中导入package.json:
// 导入模块成员
import { log } from './logger'
import messages from './messages'
import { name, version } from '../package.json' // here
// 使用模块成员
const msg = messages.hi
log(msg)
log(name) // here
log(version) // here
打包后的./dist/bundle.js文件:
const log = msg => {
console.log('---------- INFO ----------');
console.log(msg);
console.log('--------------------------');
};
var messages = {
hi: 'Hey Guys, I am zce~'
};
var name = "01-getting-started"; // here
var version = "0.1.0"; // here
// 导入模块成员
// 使用模块成员
const msg = messages.hi;
log(msg);
log(name); // here
log(version); // here
json中用到的属性被打包进来了,没用到的属性被TreeShaking移除掉了。
Rollup 加载NPM模块
Rollup不能像webpack那样通过模块名称加载npm模块,为了抹平差异,Rollup官方提供了一个插件rollup-plugin-node-resolve,通过这个插件,就可以在代码中使用模块名称导入模块。
安装插件:
yarn add rollup-plugin-node-resolve --dev
rollup.config.js:
import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve' // here
export default {
input: './src/index.js',
output: {
file: './dist/bundle.js',
formate: 'iife'
},
plugins: [
json(),
resolve() // here
]
}
./src/index.js:
// 导入模块成员
import { log } from './logger'
import messages from './messages'
import { name, version } from '../package.json'
import _ from 'lodash-es' // here
// 使用模块成员
const msg = messages.hi
log(msg)
log(name)
log(version)
log(_.camelCase('hello word')) // here
Rollup 加载 CommonJS模块
安装插件:
yarn add rollup-plugin-commonjs
rollup.config.js:
import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs' // here
export default {
input: './src/index.js',
output: {
file: './dist/bundle.js',
formate: 'iife'
},
plugins: [
json(),
resolve(),
commonjs() // here
]
}
./src/cjs.js:
module.exports = {
foo: 'bar'
}
./src/index.js:
// 导入模块成员
import { log } from './logger'
import messages from './messages'
import { name, version } from '../package.json'
import _ from 'lodash-es'
import cjs from './cjs' // here
// 使用模块成员
const msg = messages.hi
log(msg)
log(name)
log(version)
log(_.camelCase('hello word'))
log(cjs) // here
打包后的bundle.js:
var cjs = {
foo: 'bar'
};
// 导入模块成员
// 使用模块成员
const msg = messages.hi;
log(msg);
log(name);
log(version);
log(lodash.camelCase('hello word'));
log(cjs);
Rollup 代码差分
使用动态导入的方式实现模块的按需加载,Rollup内部会自动去处理代码的拆分,也就是分包。
Rollup.config.js:
import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: './src/index.js',
output: {
// file: 'dist/bundle.js',
// format: 'iife',
dir: 'dist',
format: 'amd'
},
plugins: [
json(),
resolve(),
commonjs()
]
}
./src/index.js:
import('./logger').then(({ log }) => {
log('code splitting~')
})
Rollup 多入口打包
rollup.config.js:
import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
// input: './src/index.js',
// input: ['src/index.js', 'src/album.js'], // 多入口打包
input: { // 这种写法也可以进行多入口打包
foo: 'src/index.js',
bar: 'src/album.js'
},
output: {
// file: 'dist/bundle.js',
// format: 'iife',
dir: 'dist', // 动态导入时会分包成多文件
format: 'amd' // 动态导入不支持iife
},
plugins: [
json(),
resolve(),
commonjs()
]
}
注意此时生成的js文件就要以AMD标准的require方式引入
Rollup、Webpack选用原则
Rollup优势
- 输出结果更加扁平,执行效率更高
- 自动移除未引用的代码
- 打包结果依然完全可读
Rollup缺点
- 加载非ESM的第三方模块比较复杂
- 模块最终都会被打包到一个函数中,无法实现HMR
- 浏览器环境中,代码拆分功能依赖AMD库
如果我们正在开发应用程序,需要引入大量的第三方库,代码量又大,需要分包打包,Rollup的作用则会比较欠缺。
如果我们正在开发一个框架或者类库,Rollup的这些优点则非常有必要,缺点则可以忽略。所以大多数知名框架/库都在使用Rollup作为模块打包器。
总结:Webpack大而全,Rollup小而美。
选择标准:
- 开发应用程序选择Webpack
- 开发框架/库使用Rollup