Rollup 简介 #
什么是 Rollup? #
Rollup 是一个 JavaScript 模块打包器,它将小块代码编译成大块复杂的代码,例如库或应用程序。Rollup 使用 ES 模块(ES Modules)标准,而不是之前的 CommonJS 或 AMD 等特殊解决方案,这意味着你可以无缝地使用现代 JavaScript 模块系统。
核心定位 #
text
┌─────────────────────────────────────────────────────────────┐
│ Rollup │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ ES模块优先 │ │ Tree-shaking│ │ 输出格式 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 插件系统 │ │ 代码分割 │ │ 高性能 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Rollup 的历史 #
发展历程 #
text
2015年 ─── Rollup 项目启动
│
│ Rich Harris 开发
│ 专注于 ES 模块打包
│
2016年 ─── Tree-shaking 革命
│
│ 引入革命性的 Tree-shaking
│ 消除未使用的代码
│
2017年 ─── 生态系统扩展
│
│ 插件系统完善
│ 社区快速增长
│
2018年 ─── 代码分割支持
│
│ 动态导入支持
│ 更灵活的输出配置
│
2020年 ─── Rollup 2.0
│
│ 性能大幅提升
│ 更好的 Source Map
│
2023年 ─── Rollup 3.0
│
│ 原生 ESM 支持
│ 改进的插件 API
│
至今 ─── 行业标准
│
│ Vue、React 等库的选择
│ Vite 的底层引擎
里程碑版本 #
| 版本 | 时间 | 重要特性 |
|---|---|---|
| 0.1.0 | 2015 | 首次发布,基础打包功能 |
| 0.30 | 2016 | Tree-shaking 功能 |
| 0.50 | 2017 | 代码分割支持 |
| 1.0 | 2019 | 稳定版本发布 |
| 2.0 | 2020 | 性能优化,更好的 Source Map |
| 3.0 | 2022 | 原生 ESM 支持,新插件 API |
| 4.0 | 2023 | Rust 编写的解析器,性能飞跃 |
为什么选择 Rollup? #
传统打包的问题 #
在没有 Rollup 之前,JavaScript 打包面临以下问题:
javascript
// CommonJS 模块
const lodash = require('lodash');
const result = lodash.merge({}, { a: 1 });
// 打包后包含整个 lodash(70KB+)
// 即使只使用了 merge 方法
Rollup 的解决方案 #
javascript
// ES 模块
import { merge } from 'lodash-es';
const result = merge({}, { a: 1 });
// 打包后只包含 merge 相关代码
// Tree-shaking 消除未使用的代码
Rollup 的核心特点 #
1. Tree-shaking #
Rollup 最著名的特性,静态分析代码,消除未使用的代码:
javascript
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
// main.js
import { add } from './math.js';
console.log(add(1, 2));
// 打包后只包含 add 函数
// subtract 和 multiply 被移除
2. 多种输出格式 #
支持多种模块格式输出:
javascript
// rollup.config.js
export default {
input: 'src/main.js',
output: [
{ file: 'dist/bundle.js', format: 'iife' }, // 浏览器
{ file: 'dist/bundle.cjs', format: 'cjs' }, // Node.js
{ file: 'dist/bundle.mjs', format: 'es' }, // ES 模块
{ file: 'dist/bundle.umd.js', format: 'umd' }, // UMD
]
};
3. ES 模块优先 #
原生支持 ES 模块,无需额外配置:
javascript
// 直接使用 ES 模块语法
import { something } from './module.js';
export default function() { ... }
4. 高效的代码分割 #
javascript
// 动态导入
async function loadModule() {
const { heavyFunction } = await import('./heavy.js');
heavyFunction();
}
// 自动代码分割
// heavy.js 会被打包成单独的 chunk
5. 强大的插件系统 #
javascript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import terser from '@rollup/plugin-terser';
export default {
plugins: [
resolve(), // 解析 node_modules
commonjs(), // 转换 CommonJS
terser(), // 压缩代码
]
};
Rollup 与其他打包工具对比 #
Rollup vs Webpack #
| 特性 | Rollup | Webpack |
|---|---|---|
| 学习曲线 | 较低 | 较高 |
| 配置复杂度 | 简单 | 复杂 |
| Tree-shaking | ✅ 原生支持 | ⚠️ 需配置 |
| 输出格式 | 多种 | 主要 bundle |
| 代码分割 | ✅ 支持 | ✅ 强大 |
| 热更新 | ⚠️ 需插件 | ✅ 原生支持 |
| 适用场景 | 库开发、简单应用 | 复杂应用 |
| 打包速度 | 快 | 较慢 |
| 输出体积 | 小 | 较大 |
Rollup vs Vite #
| 特性 | Rollup | Vite |
|---|---|---|
| 定位 | 打包器 | 构建工具 |
| 开发服务器 | ❌ 无 | ✅ 内置 |
| HMR | ❌ 无 | ✅ 内置 |
| 底层引擎 | - | Rollup |
| 配置 | 手动 | 约定优先 |
| 适用场景 | 库开发 | 应用开发 |
Rollup vs esbuild #
| 特性 | Rollup | esbuild |
|---|---|---|
| 语言 | JavaScript | Go |
| 速度 | 快 | 极快 |
| Tree-shaking | ✅ 优秀 | ⚠️ 基础 |
| 插件生态 | ✅ 丰富 | 🔄 发展中 |
| 输出格式 | 多种 | 多种 |
| Source Map | ✅ 完善 | ✅ 支持 |
Rollup 的应用场景 #
1. 库开发 #
Rollup 是开发 JavaScript 库的首选:
javascript
// my-library/rollup.config.js
export default {
input: 'src/index.js',
output: [
{ file: 'dist/my-lib.cjs.js', format: 'cjs' },
{ file: 'dist/my-lib.esm.js', format: 'es' },
{ file: 'dist/my-lib.umd.js', format: 'umd', name: 'MyLib' },
]
};
知名案例:
- Vue 3
- React
- Three.js
- D3.js
- Lodash ES
2. 简单应用 #
对于不需要复杂功能的应用:
javascript
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true
},
plugins: [resolve()]
};
3. 组件库 #
打包 UI 组件库:
javascript
export default {
input: 'src/components/index.js',
output: [
{ dir: 'dist', format: 'es', preserveModules: true },
],
external: ['vue', 'react']
};
Rollup 的核心概念 #
输入(Input) #
入口文件,打包的起点:
javascript
// 单入口
input: 'src/main.js'
// 多入口
input: ['src/main.js', 'src/admin.js']
// 对象形式
input: {
main: 'src/main.js',
admin: 'src/admin.js'
}
输出(Output) #
打包结果配置:
javascript
output: {
file: 'dist/bundle.js', // 输出文件
format: 'es', // 输出格式
name: 'MyLibrary', // UMD 全局变量名
sourcemap: true, // 生成 sourcemap
}
插件(Plugins) #
扩展 Rollup 功能:
javascript
plugins: [
resolve(), // 解析模块
commonjs(), // 转换 CommonJS
json(), // 导入 JSON
terser(), // 压缩代码
]
外部模块(External) #
排除不打包的依赖:
javascript
external: ['lodash', 'vue', 'react']
// 或使用函数
external: (id) => {
return id.includes('node_modules');
}
Rollup 的工作流程 #
text
┌─────────────────────────────────────────────────────────────┐
│ Rollup 打包流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 入口文件 │ -> │ 构建依赖图 │ -> │ 模块解析 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 输出文件 │ <- │ 代码生成 │ <- │ Tree-shake│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
详细步骤 #
- 入口解析:从入口文件开始分析
- 依赖图构建:递归分析所有依赖关系
- 模块解析:解析每个模块的内容
- Tree-shaking:标记和移除未使用的代码
- 代码生成:生成最终的打包代码
- 输出写入:写入到输出文件
输出格式详解 #
ES Module(es) #
现代 JavaScript 模块格式:
javascript
// 输出
import { foo } from './foo.js';
export default function() { ... }
适用场景:
- 现代浏览器
- Node.js(ESM 支持)
- 打包工具进一步处理
CommonJS(cjs) #
Node.js 模块格式:
javascript
// 输出
'use strict';
var foo = require('./foo.js');
module.exports = function() { ... }
适用场景:
- Node.js 环境
- 旧版打包工具
UMD(umd) #
通用模块定义:
javascript
// 输出
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.MyLib = factory());
})(this, (function () { ... }));
适用场景:
- 浏览器
<script>标签 - AMD 加载器
- CommonJS 环境
IIFE(iife) #
立即执行函数:
javascript
// 输出
(function () {
'use strict';
// ...代码
})();
适用场景:
- 浏览器
<script>标签 - 不需要模块系统
System(system) #
SystemJS 模块格式:
javascript
// 输出
System.register('my-lib', [], function (exports) {
'use strict';
return {
execute: function () {
exports('default', function() { ... });
}
};
});
适用场景:
- SystemJS 加载器
学习路径 #
text
入门阶段
├── 安装与配置
├── 基本使用
├── 命令行参数
└── 配置文件
进阶阶段
├── 插件系统
├── 代码分割
├── Tree-shaking
└── 多入口打包
高级阶段
├── 自定义插件
├── 高级配置
├── 性能优化
└── 与其他工具集成
实战阶段
├── 库开发实战
├── 应用开发
├── 组件库打包
└── 最佳实践
下一步 #
现在你已经了解了 Rollup 的基本概念,接下来学习 安装与配置 开始实际使用 Rollup!
最后更新:2026-03-28