一、简介
rollup 是一个 ES Module 模块打包器,可以将小块代码编译成大块复杂的代码,其源码中模块的导入导出采用的是ES6模块语法,即源码需要采用ES6语法进行编写。
rollup与webpack的对比:
- rollup只能处理js模块,而webpack可以处理任何资源,可以把所有的资源都当成模块进行处理。
- rollup多适用于类库的打包,打包的代码需要供他人使用,webpack多适用于应用的打包。
- rollup一般不会产生额外的代码(除了必要的cjs, umd头外),所以rollup打包出来的代码执行更快、可读性更强,webpack由于功能强大,所以会产生很多额外的代码、打包出来的文件较大、执行较慢、可读性较差
- rollup会将所有资源放同一个地方,一次性加载,利用 tree-shake特性来剔除未使用的代码,减少冗余,而webpack则是拆分代码、按需加载
二、安装与基本使用
要使用rollup,需要在全局进行安装,如:
// 全局安装rollup
> sudo npm install --global rollup
rollup安装完成后,就可以通过rollup命令进行打包了:
① rollup 模块入口文件:
// 进入项目根目录下,并以src目录下的index.js作为模块入口进行打包
> rollup ./src/index.js
此时可以看到直接在控制台中输出了模块打包结果,因为没有指定将打包结果输出到哪个文件下,所以会直接输出打包结果到控制台中。
② 指定模块输出, --file
// 将打包结果输出到当前目录下的bundle.js文件中
> rollup ./src/index.js --file bundle.js
③ 指定打包后的模块输出格式,--format
// 将模块打包成iife格式,即将模块放到匿名自执行函数中执行
> rollup ./src/index.js --file bundle.js --format iife
如果没有指定format,那么默认会输出为es格式。rollup支持的模块输出格式为: es、cjs、amd、umd、iife、system。其中cjs就是CommonJS模块规范。
通过format打包输出格式的设置,可以让打包后的代码更好的支持浏览器或者node环境。也就是说,rollup打包前源码只能采用ES6模块,但是打包后可以通过format的设置让其支持node环境。
④ 指定打包后模块的输出结果接收变量,--name
即指定一个变量用于接收打包后的模块输出结果
// 用result变量来接收模块的输出结果
> rollup ./src/index.js --file bundle.js --format iife --name result
输出结果如下:
var result = (function () {
'use strict';
const foo = "foo";
return foo;
}());
⑤ 源码中模块的导入导出必须使用es6模块语法
如果源码中模块的导入导出采用的是CommonJS模块语法,那么打包后仍然会包含require,如:
// foo.js
const foo = "foo";
module.exports = foo;
// index.js
const foo = require("./foo");
console.log(foo);
module.exports = foo;
> rollup ./src/index.js --file bundle.js --format cjs
打包后的输出结果中仍然包含require语法
'use strict';
const foo = require("./foo");
console.log(foo);
module.exports = foo;
从打包结果可以看到,源码中的require语句原封不动输出到了bundle.js中,虽然打包过程中没有发生错误,但是foo.js模块的代码并没有被打包到bundle.js模块中,也就是说,其实打包是失败的。
如果采用import...from...去引入foo.js,如:
import foo from "./foo";
console.log(foo);
那么打包的过程就会报错,如下:
15: console.log(foo);
Error: 'default' is not exported by src/foo.js, imported by src/index.js
即rollup认为foo.js中没有default导出,因为rollup无法识别CommonJS模块语法。
三、使用配置文件打包
要使用配置文件进行打包,需要带上-c参数,后面接配置文件即可,配置文件默认位置在项目根目录下,默认文件名为rollup.config.js。
① 在项目根目录下新建一个rollup.config.js文件
// rollup.config.js
export default {
input: "src/index.js", // 指定模块入口
output: {
file: "dist/bundle.js", // 指定模块输出文件路径
name: "res", // 用于接收模块的输出的变量
format: "cjs", // 指定模块输出格式
sourcemap: true // 开启sourcemap
}
}
这里的output和webpack的output不一样,webpack需要配置一个path作为打包输出目录,并且必须是绝对路径,而rollup则不需要配置path,直接在file里面配置相对路径即可,如上即可将模块打包输出到项目根目录下的dist目录下。
② 通过rollup -c 加载配置文件进行打包
// 使用项目根目录下的rollup.config.js配置文件进行打包
> rollup -c
③ 打包的时候还可以添加一个-w参数,表示监听源文件的变化,如果发生变化,那么将重新打包。
四、使用插件
rollup也支持我们使用一些插件来为打包提供更大的灵活性。Webpack 中划分了 Loader、Plugin 和 Minimizer 三种扩展方式,而插件是 Rollup 的唯一的扩展方式。
babel插件
使用babel插件可以将我们的es6语法编译成es5语法。
① 安装rollup-plugin-babel插件
// 首先安装rollup-plugin-babel插件
> npm install rollup-plugin-babel --save-dev
② 在配置文件中引入babel插件
import bable from "rollup-plugin-babel"; // 引入babel插件
export default {
input: "src/index.js",
output: {
file: "bundle.js",
format: "cjs"
},
plugins: [
bable({ // 添加babel插件
exclude: "node_modules/**" // 排除node_modules下的文件
})
]
}
③ 添加.babelrc文件
// 安装babel预设
> npm install @babel/preset-env --save-dev
即用@babel/preset-env模块中定义的预设进行处理,所以需要安装@babel/preset-env模块
{
"presets": [
"@babel/preset-env" // 添加安装好的预设
]
}
此时再打包,源码中的es6语法就能被转换为es5了。
serve插件
使用serve插件可以让我们启动一个server
① 安装rollup-plugin-serve插件
// 安装rollup-plugin-serve插件
> npm install rollup-plugin-serve --save-dev
② 在配置文件中引入serve插件
import bable from "rollup-plugin-babel";
import serve from "rollup-plugin-serve";
export default {
input: "src/index.js",
output: {
file: "bundle.js",
format: "cjs"
},
plugins: [
bable({
exclude: "node_modules/**"
}),
process.env.ENV === "development" ? serve({
port: 3000,
contentBase: ["public", "."], // 静态资源所在目录
}) : null
]
}
此时再打包就会启动一个server了,通过浏览器访问http://localhost:3000/index.html
就可以访问到./public目录中的index.html资源了。
加载CommonJS规范的模块
上面说过,rollup只能解析使用ES模块规范的模块。而大部分第三方模块都是采用CommonJS模块规范编写,如果要让rollup能够解析CommonJS模块规范的模块,那么我们需要通过@rollup/plugin-commonjs插件。
// foo.js采用CommonJS模块规范导出
module.exports = "foo";
// index.js
import foo from "./foo"; // 引入CommonJS模块
console.log(foo);
import commonjs from "@rollup/plugin-commonjs"
export default {
input: "./src/index.js",
output: {
file: "dist/bundle.js"
},
plugins: [
commonjs() // 支持解析CommonJS模块
]
}
webpack之所以不需要插件就能解析CommonJS模块,是因为webpack中对于所有的模块导入语句都替换为了自己的模块导入语句__webpack_require__。
加载NPM中的模块
Rollup 默认只能够按照文件路径的方式加载本地的模块文件,对于 node_modules 目录中的第三方模块,并不能像node一样,直接通过模块名称直接导入。如果我们想让rollup支持像node的方式加载第三方模块,那么需要通过@rollup/plugin-node-resolve插件,如:
// index.js
import react from "react"; // 引入第三方模块react
console.log(react);
import resolve from "@rollup/plugin-node-resolve";
export default {
input: "./src/index.js",
output: {
file: "dist/bundle.js"
},
plugins: [
commonjs(), // 支持解析CommonJS模块
resolve() // 支持从node_modules中引入模块
]
}