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│              │
│  └──────────┘    └──────────┘    └──────────┘              │
│                                                              │
└─────────────────────────────────────────────────────────────┘

详细步骤 #

  1. 入口解析:从入口文件开始分析
  2. 依赖图构建:递归分析所有依赖关系
  3. 模块解析:解析每个模块的内容
  4. Tree-shaking:标记和移除未使用的代码
  5. 代码生成:生成最终的打包代码
  6. 输出写入:写入到输出文件

输出格式详解 #

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