嘿,前端开发小伙伴们!今天咱们来聊一聊Rollup这个有点低调但超级实用的JavaScript模块打包工具。说实话,在webpack一统江湖的年代,Rollup这样的工具往往被很多人忽略了。但它绝对是个宝藏工具,尤其是对于库的开发者来说简直是福音!

什么是Rollup?为啥要学它?

Rollup是一个JavaScript模块打包器,专注于ES模块(ESM)的处理。它于2015年由Rich Harris(没错,就是Svelte的创造者!)开发,主打简洁高效。

你可能会问:“都有webpack了,为啥还要学Rollup?”(我刚开始也是这么想的…)

几个超级吸引人的原因:

  1. 代码精简 - Rollup生成的包体积小,这是因为它有个杀手锏功能——Tree Shaking!它能自动移除未使用的代码。
  2. 适合库开发 - 如果你在开发一个JavaScript库,Rollup绝对是首选(Vue、React、Three.js等都在用它)。
  3. 配置简单 - 相比webpack复杂的配置,Rollup配置文件简单易懂,新手友好!
  4. 输出格式灵活 - 支持多种模块格式,包括ESM、CommonJS、UMD等。

总之,如果你厌倦了webpack的复杂配置,或者正准备开发一个库,是时候了解一下Rollup了!

开始使用Rollup

安装

首先,我们需要安装Rollup。可以全局安装或者作为项目依赖安装:

# 全局安装
npm install --global rollup
# 项目依赖安装(推荐)
npm install --save-dev rollup

我个人更推荐第二种方式,这样不同项目可以使用不同版本的Rollup,避免兼容性问题。

基本使用

让我们从一个简单的例子开始!

首先,创建一个项目结构:

my-rollup-project/
├── src/
│   ├── main.js
│   └── modules/
│       └── calculator.js
├── package.json
└── rollup.config.js

calculator.js中,我们定义一些简单的计算函数:

// src/modules/calculator.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;
}
export function divide(a, b) {
if (b === 0) {
throw new Error("除数不能为零!");
}
return a / b;
}

然后在main.js中引入并使用这些函数:

// src/main.js
import { add, multiply } from './modules/calculator.js';
console.log(add(1, 2)); // 输出: 3
console.log(multiply(3, 4)); // 输出: 12
export default function calculator() {
return {
add,
multiply
};
}

注意看,我们只导入了addmultiply函数,没有用到subtractdivide。这就是Tree Shaking大显身手的地方!

接下来,创建一个Rollup配置文件rollup.config.js

// rollup.config.js
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'cjs' // CommonJS格式
}
};

这个配置文件超级简单:

  • input: 入口文件
  • output: 输出配置
    • file: 输出文件路径
    • format: 输出格式(这里用的是CommonJS)

最后,在package.json中添加构建脚本:

{
"name": "my-rollup-project",
"version": "1.0.0",
"scripts": {
"build": "rollup -c"
},
"devDependencies": {
"rollup": "^3.20.0"
}
}

运行构建命令:

npm run build

完成后,查看生成的dist/bundle.js文件,你会发现它只包含了我们实际使用的addmultiply函数,subtractdivide函数被自动移除了!这就是Tree Shaking的魔力!

输出格式

Rollup支持多种输出格式,适应不同的使用场景:

  • esm/es: ES模块格式,现代浏览器原生支持
  • cjs: CommonJS格式,适用于Node.js环境
  • umd: 通用模块定义,同时支持浏览器和Node.js
  • iife: 立即执行函数,适合作为<script>直接在浏览器中使用

修改配置文件以输出多种格式:

export default {
input: 'src/main.js',
output: [
{
file: 'dist/bundle.cjs.js',
format: 'cjs'
},
{
file: 'dist/bundle.esm.js',
format: 'es'
},
{
file: 'dist/bundle.umd.js',
format: 'umd',
name: 'MyCalculator' // UMD格式需要指定一个全局变量名
}
]
};

这样一次构建就能生成三种不同格式的文件,超级方便!

使用插件

Rollup的核心功能相当精简,但通过插件系统可以扩展其功能。这些插件能帮助处理各种资源、转换代码、优化输出等。

以下是一些常用的Rollup插件:

1. @rollup/plugin-node-resolve

这个插件允许Rollup从node_modules中引入第三方模块。

npm install --save-dev @rollup/plugin-node-resolve

修改配置文件:

import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'cjs'
},
plugins: [
resolve()
]
};

2. @rollup/plugin-commonjs

这个插件将CommonJS模块转换为ES模块,这样Rollup就能处理它们了。

npm install --save-dev @rollup/plugin-commonjs

修改配置文件:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
// ...
plugins: [
resolve(),
commonjs()
]
};

3. @rollup/plugin-babel

如果你需要使用Babel来转换代码(比如使用最新的JavaScript特性),可以使用这个插件:

npm install --save-dev @rollup/plugin-babel @babel/core @babel/preset-env

创建Babel配置文件.babelrc

{
"presets": [["@babel/preset-env", { "modules": false }]]
}

修改Rollup配置:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
export default {
// ...
plugins: [
resolve(),
commonjs(),
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**'
})
]
};

4. @rollup/plugin-terser

对打包后的代码进行压缩:

npm install --save-dev @rollup/plugin-terser

修改配置:

import terser from '@rollup/plugin-terser';
export default {
// ...
plugins: [
// ...其他插件
terser()
]
};

实际项目配置示例

下面是一个较为完整的Rollup配置,包含了开发库时常用的设置:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import terser from '@rollup/plugin-terser';
import pkg from './package.json' assert { type: 'json' };
export default [
// 浏览器友好的UMD构建
{
input: 'src/main.js',
output: {
name: 'myLibrary',
file: pkg.browser,
format: 'umd'
},
plugins: [
resolve(),
commonjs(),
babel({
babelHelpers: 'bundled',
exclude: ['node_modules/**']
}),
terser()
]
},
// CommonJS和ES模块构建
{
input: 'src/main.js',
output: [
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' }
],
plugins: [
babel({
babelHelpers: 'bundled',
exclude: ['node_modules/**']
})
]
}
];

对应的package.json配置:

{
"name": "my-awesome-library",
"version": "1.0.0",
"main": "dist/my-library.cjs.js",
"module": "dist/my-library.esm.js",
"browser": "dist/my-library.umd.js",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w"
}
}

Rollup vs Webpack:何时选择哪个?

很多人会问:“Rollup和Webpack到底哪个更好?”

老实说,这不是非此即彼的选择。它们各有优势,适合不同场景:

选择Rollup的情况:

  1. 开发JavaScript库或组件 - Rollup的Tree Shaking和干净的输出使其成为库开发的理想选择。
  2. 代码体积敏感 - 如果你需要最小化的输出体积。
  3. 配置简单 - 如果你厌倦了复杂的webpack配置。
  4. 项目结构简单 - 主要处理JavaScript模块,没有复杂的资源需求。

选择Webpack的情况:

  1. 开发应用程序 - 特别是有大量静态资源的复杂应用。
  2. 需要代码分割和动态导入 - Webpack在这方面更成熟。
  3. 需要处理多种资源 - 图片、CSS、字体等各种资源。
  4. HMR需求 - 热模块替换在开发体验上很重要。

个人经验:我会在开发库时使用Rollup,开发应用时使用Webpack或Vite(基于Rollup但针对应用开发优化)。

进阶技巧

1. 外部依赖

开发库时,你通常不想将所有依赖都打包进去。可以使用external选项标记外部依赖:

export default {
// ...
external: ['lodash', 'react'],
// ...
};

这样,这些依赖将不会被打包,而是作为引用保留在代码中。

2. Sourcemaps

为了方便调试,可以生成sourcemaps:

export default {
// ...
output: {
// ...
sourcemap: true
}
};

3. 动态导入

Rollup支持代码分割和动态导入:

// 动态导入示例
import('./modules/heavy-module.js').then(module => {
// 使用模块
});

配置中需要指定代码分割的输出目录:

export default {
// ...
output: {
dir: 'dist',
format: 'es',
// file属性在使用代码分割时不能使用
}
};

常见问题与解决方案

1. “Unresolved dependencies” 错误

如果你看到类似错误:

(!) Unresolved dependencies
https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency

这通常意味着Rollup无法解析某些导入。解决方案是使用@rollup/plugin-node-resolve插件,或者将该依赖标记为外部依赖。

2. CommonJS模块问题

如果你使用的库是CommonJS格式,Rollup可能无法正确处理。使用@rollup/plugin-commonjs插件解决。

3. 全局变量访问

在UMD构建中,如果你需要访问全局变量(如windowdocument),可以使用globals选项:

export default {
// ...
output: {
// ...
format: 'umd',
globals: {
jquery: '$' // 将jquery映射到全局变量$
}
},
external: ['jquery'] // 标记jquery为外部依赖
};

小结

Rollup虽然没有Webpack那么出名,但它在JavaScript库开发领域绝对是一把利器!它的配置简单、输出干净、Tree Shaking出色,非常值得学习和使用。

如果你正在考虑开发一个JavaScript库,或者只是想尝试一个更轻量级的打包工具,绝对值得给Rollup一个机会!

最后,如果你已经习惯了Webpack,也不必急着完全迁移。两者可以共存,在适合的场景使用适合的工具。

希望这篇教程对你有所帮助!祝你编码愉快!

posted on 2025-10-20 08:09  ycfenxi  阅读(0)  评论(0)    收藏  举报