定义
官方对rollup的定义:
Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex,such as a library or application.
Rollup是一个JavaScript的模块化打包工具,可以帮助我们编译小的代码到一个大的、复杂的代码中,比如一个库或者一个应用程序;
从定义上看,Rollup与之前我们所学的webpack在定位上是很相似的。实际上Rollup就是对标Webpack的。
- rollup也是一个模块化的打包工具,但是Rollup主要是针对ES Module进行打包的;(webpack支持esm、cjs、amd等模块化)
- rollup更多时候是专注于处理JavaScript代码的(当然也可以处理css、font、vue等文件);
另外rollup的配置和理念相对于webpack来说,更加的简洁和容易理解;
webpack和rollup各自的应用场景
通常在实际项目开发过程中,我们都会使用webpack(比如vue、react、angular脚手架创建的项目都是基于webpack的);
在对js库进行打包时,我们通常会使用rollup(比如vue、react、dayjs源码本身都是基于rollup的);
看到这里,我们不得不产生了一个疑惑。它们两者既然是对标的,那为什么rollup会更适用于库的开发呢?
查阅了网上很多文章,都对于这个问题没有说清楚。网上文章的说法大多只是rollpu是更适合处理js库的,而且打包出来的文件体积会比webpack 小。
那接下来我们带着这个问题去更深入地学下rollup。看能不能分析出答案来。
基本使用
安装:
npm install rollup -D
在根目录下创建rollup.config.js
配置文件
//rollup.config.js
export default {
input: "./src/main.js",
//output能接收一个数组,rollup支持创建不同应用场景的打包文件
output: [
{
format: "umd",
name: "umdbundle",
file: "dist/bundle.umd.js"
},
{
format: "cjs",
file: "dist/bundle.commonjs.js"
},
{
format: "amd",
file: "dist/bundle.amd.js"
},
{
format: "es",
file: "dist/bundle.es.js"
},
{
format: "iife",
name: "iifebundle",
file: "dist/bundle.browser.js"
}
]
}
//package.json
"scripts": {
"build": "rollup -c"
},
命令行输入npm run build后就可以看到打包出来的文件了:
我们可以看到根据我们对不同场景的配置,分别创建了不同场景的bundle文件。假如这是个第三方js库,那么用户在使用时,就可以根据自己当前的场景环境,拿对应的bundle文件即可。(比如在node环境下,就只能commonjs的bundle文件)
而webpack不是这样去处理模块化的。webpack会帮我们写很多支持模块化的代码,保证代码可以在各个场景环境下运行。(webpack模块化方面可以回顾之前的 06、webpack实现模块化原理)
至此,我们就知道 为什么rollup会更适用于库的开发 这个问题的答案了。
- rollup可以针对各个应用场景都生成对应的bundle文件;
- 用户真正拿到的库文件体积更小。
rollup处理引入的第三方库
我们最开始看rollup定义时,发现Rollup主要是针对ES Module进行打包。
也就是说我们的代码中模块化方面只支持写ES Module。如果写了其他的模块化语法,比如commonJS,就会报错。
当我们的项目引入了第三方库,会产生如下几个问题:
如果第三方库使用的是commonJs模块化,那我们需要怎么处理?
rollup默认不会去node_modules里找第三方库,我们需要怎么处理?
安装解决commonjs的库:
npm install @rollup/plugin-commonjs -D
安装解决node_modules的库:
npm install @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/main.js",
output: {
format: "umd",
name: "unmbundle",
file: "dist/why.umd.js",
//如果使用了external,还需要配置globals全局对象
globals: {
lodash: "_",
},
},
//建议使用第三方库时,采用全局引入+external(全局引入可以在html文件里引入)。这样就可以让第三方库与我们项目代码不被打包到同一bundle文件里
external: ["lodash"],
plugins: [
//支持导出可以为commonjs模块化
commonjs(),
//支持rollup会去node_modules下找第三方库
resolve()
],
};
通过上述配置,我们就可以正常使用导入的第三方库。
rollup自动化构建案例
- 解决commonjs和第三方库问题
- Babel转换代码
- Teser代码压缩
- 处理css文件
- 处理vue文件
- 搭建本地服务器
- 区分开发环境 ```javascript //rollup.config.js import commonjs from “@rollup/plugin-commonjs”; import resolve from “@rollup/plugin-node-resolve”; import babel from “@rollup/plugin-babel”; import { terser } from “rollup-plugin-terser”; import postcss from ‘rollup-plugin-postcss’; import vue from ‘rollup-plugin-vue’; import replace from ‘rollup-plugin-replace’; import serve from ‘rollup-plugin-serve’; import livereload from ‘rollup-plugin-livereload’;
const isProduction = process.env.NODE_ENV === ‘production’; const plugins = [ commonjs(), resolve(), //使用replace注入环境变量 replace({ ‘process.env.NODE_ENV’: JSON.stringify(process.env.NODE_ENV) }), //使用babel进行一些转化 babel({ babelHelpers: “bundled”, }), //处理css文件 postcss(), //处理vue文件 vue(), ]
if (isProduction) { //production模式下,使用terser丑化压缩代码 plugins.push(terser()) } else { const devPlugins = [ //开发模式下,开启本地服务 serve({ // open: true, // 是否打开浏览器 port: 8080, // 监听哪一个端口 contentBase: “.” // 服务哪一个文件夹 }), //文件发生变化自动刷新浏览器 livereload() ] plugins.push(…devPlugins); }
export default { input: “./src/main.js”, output: { format: “umd”, name: “whyUtils”, file: “dist/why.umd.js”, globals: { lodash: “_”, }, }, external: [“lodash”], plugins, };
```json
//package.json
"scripts": {
"build": "rollup -c --environment NODE_ENV:production",
//-w:(--watch)开启文件监听
"serve": "rollup -c --environment NODE_ENV:development -w"
},