Rollup 是一个用于 JavaScript 的模块打包工具,它将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式,而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许你自由无缝地组合你最喜欢的库中最有用的个别函数。这在未来将在所有场景原生支持,但 Rollup 让你今天就可以开始这样做。
快速开始
编译为包含自执行函数('iife')的 <script>。
rollup main.js --file bundle.js --format iife
对于浏览器:
编译为包含自执行函数('iife')的 <script>。
rollup main.js --file bundle.js --format iife
对于 Node.js:
编译为一个 CommonJS 模块 ('cjs')
rollup main.js --file bundle.js --format cjs
对于浏览器和 Node.js:
UMD 格式需要一个包名
rollup main.js --file bundle.js --format umd --name "myBundle"
背景
将项目分解为较小的独立部分通常可以使软件开发更加容易,因为这通常可以消除意外的交互,并大大减少你需要解决的问题的复杂性,而仅仅是首先编写较小的项目 并不一定是最好的方式。不幸的是,JavaScript 在历史上并没有将这种能力作为语言的核心特性之一。这在 ES6 版本的 JavaScript 中得到了改变,该版本包括一种语法,用于导入和导出函数和数据,以便它们可以在单独的脚本之间共享。
该规范现在已经稳定,但仅在现代浏览器中实现,并未在 Node.js 中完全落地。Rollup 允许你使用新的模块系统编写代码,然后将其编译回现有的支持格式,例如 CommonJS 模块、AMD 模块和 IIFE 样式脚本。这意味着你可以编写 对未来兼容 的代码,并且还可以获得以下几点收益……
除屑优化(Tree-Shaking)
除了可以使用 ES 模块之外,Rollup 还可以静态分析你导入的代码,并将排除任何实际上没有使用的内容。这使你可以在现有的工具和模块的基础上构建,而不需要添加额外的依赖项或使项目的大小变得臃肿。
例如,使用 CommonJS 必须导入整个工具或库。
// 使用 CommonJS 导入整个 utils 对象
const utils = require('./utils');
const query = 'Rollup';
// 使用 utils 对象的 ajax 方法。
utils.ajax(`https://api.example.com?search=${query}`).then(handleResponse);
// 使用 ES 模块,我们不需要导入整个 utils 对象,而只需导入我们需要的一个 ajax 函数:
// 使用 ES6 的 import 语句导入 ajax 函数。
import { ajax } from './utils';
const query = 'Rollup';
// 调用 ajax 函数
ajax(`https://api.example.com?search=${query}`).then(handleResponse);
因为 Rollup 只包含最少的内容,因此它生成的库和应用程序更轻、更快、更简单。
由于这种方法可以利用显式的 import 和 export 语句,
因此它比仅运行最小化混淆工具更能有效检测出已编译输出代码中的未使用变量。
导入 CommonJS
Rollup 可以通过插件 导入现有的 CommonJS 模块。
发布 ES 模块
为了确保你的 ES 模块可以立即被处理 CommonJS 的工具,
例如 Node.js 和 webpack 使用,你可以使用 Rollup 编译成 UMD 或 CommonJS 格式,
然后在 package.json 文件中使用 main 属性指向编译后的版本。
如果你的 package.json 文件还有一个 module 字段,
那么像 Rollup 和 webpack 2+ 这样的可感知 ES 模块的工具将直接 导入 ES 模块版本。
配置文件
Rollup 配置文件是可选的,但它们非常强大和方便,因此推荐使用。配置文件是一个 ES 模块,它导出一个默认对象,其中包含所需的选项:
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
}
};
Rollup 与其它工具的集成
在某个时刻,你的项目可能会依赖于从 NPM 安装到 node_modules 文件夹中的软件包。与 Webpack 和 Browserify 等其他打包程序不同,Rollup 默认情况下不知道如何处理这些依赖项,我们需要添加一些配置。
让我们添加一个名为 the-answer 的简单依赖项,它导出了生命、宇宙和一切问题的答案:
npm install the-answer
如果我们更新了 src/main.js 文件…
// src/main.js
import answer from 'the-answer';
export default function () {
console.log('the answer is ' + answer);
}
npm run build 会看到警告
生成的 bundle.js 仍然可以在 Node.js 中使用,因为 import 声明会被转换为 CommonJS 的 require 语句,但是 the-answer 不会被包含在 bundle 中。为此,我们需要一个插件。
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
},
plugins: [resolve()]
};
这一次,当你运行 npm run build 时,不会发出警告 - bundle 包含了导入的模块。
UMD 格式需要一个包名
rollup main.js --file bundle.js --format umd --name “myBundle”
认识rollup
- 我们来看一下官方对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也是一个模块化的打包工具,但是Rollup主要是针对ES Module进行打包的;
- 另外webpack通常可以通过各种loader处理各种各样的文件,以及处理它们的依赖关系;
- rollup更多时候是专注于处理JavaScript代码的(当然也可以处理css、font、vue等文件);
- 另外rollup的配置和理念相对于webpack来说,更加的简洁和容易理解;
- 在早期webpack不支持tree shaking时,rollup具备更强的优势;
- 目前webpack和rollup分别应用在什么场景呢?
- 通常在实际项目开发过程中,我们都会使用webpack(比如vue、react、angular项目都是基于webpack的);
- 在对库文件进行打包时,我们通常会使用rollup(比如vue、react、dayjs源码本身都是基于rollup的);
Rollup基本使用
- 我们可以先安装rollup:
npm install --global rollup
- 创建main.js文件,打包到bundle.js文件中:
// 打包浏览器的库
npx rollup ./src/main.js -f iife -o dist/bundle.js
// 打包AMD的库
npx rollup ./src/main.js -f amd -o dist/bundle.js
// 打包CommonJS
npx rollup ./src/main.js -f cjs -o dist/bundle.js
// 打包通用的库(必须跟上name)
npx rollup ./src/main.js -f umd --name mathUtil -o dist/bundle.js
Rollup的配置文件
- 我们可以将配置信息写到配置文件中rollup.config.js文件:
export default {
input: "./src/main.js",
output:{
format:"cjs",
file:"dist/why.common.js"
}
}
- 我们可以对文件进行分别打包,打包出更多的库文件(用户可以根据不同的需求来引入):
export default {
input: "./src/main.js",
output:[
{
format:"cjs",
file:"dist/why.common.js"
},
{
format:"amd",
file:"dist/why.amd.js"
},
]
}
解决commonjs和第三方库问题
- 安装解决commonjs的库:
npm install @rollup/plugin-commonjs -D
- 安装解决node_modules的库:
npm install @rollup/plugin-node-resolve -D
- 打包和排除lodash
Babel转换代码
- 如果我们希望将ES6转成ES5的代码,可以在rollup中使用babel。
- 安装rollup对应的babel插件:
npm install @rollup/plugin-babel -D
- 修改配置文件:
- 注意:babel的位置应该是在commonjs的前面的;
- 需要配置babel.config.js文件;
Teser代码压缩
- 如果我们希望对代码进行压缩,可以使用rollup-plugin-terser:
npm install rollup-plugin-terser -D
- 配置terser:
处理css文件
- 如果我们项目中需要处理css文件,可以使用postcss:
npm install rollup-plugin-postcss postcss -D
- 配置postcss的插件:
处理vue文件
- 处理vue文件我们需要使用rollup-plugin-vue插件:
- 但是注意:默认情况下我们安装的是vue2.x的版本,所以我这里指定了一下rollup-plugin-vue的版本;
npm install rollup-plugin-vue@4.6.1 vue-template-compiler -D
- 使用vue的插件:
打包vue报错
- 在我们打包vue项目后,运行会报如下的错误:
- 这是因为在我们打包的vue代码中,用到 process.env.NODE_ENV,所以我们可以使用一个插件 rollup-pluginreplace 设置它对应的值:
npm install rollup-plugin-replace -D
- 配置插件信息:
搭建本地服务器
- 第一步:使用rollup-plugin-serve搭建服务
npm install rollup-plugin-serve -D
- 第二步:当文件发生变化时,自动刷新浏览器
npm install rollup-plugin-livereload -D
- 第三步:启动时,开启文件监听
npx rollup -c -w
区分开发环境
- 我们可以在package.json中创建一个开发和构建的脚本: