文章目录
-
- 什么是Rollup?为啥要学它?
- 开始使用Rollup
- 输出格式
- 使用插件
-
- [1. @rollup/plugin-node-resolve](#1. @rollup/plugin-node-resolve)
- [2. @rollup/plugin-commonjs](#2. @rollup/plugin-commonjs)
- [3. @rollup/plugin-babel](#3. @rollup/plugin-babel)
- [4. @rollup/plugin-terser](#4. @rollup/plugin-terser)
- 实际项目配置示例
- [Rollup vs Webpack:何时选择哪个?](#Rollup vs Webpack:何时选择哪个?)
- 进阶技巧
-
- [1. 外部依赖](#1. 外部依赖)
- [2. Sourcemaps](#2. Sourcemaps)
- [3. 动态导入](#3. 动态导入)
- 常见问题与解决方案
-
- [1. "Unresolved dependencies" 错误](#1. "Unresolved dependencies" 错误)
- [2. CommonJS模块问题](#2. CommonJS模块问题)
- [3. 全局变量访问](#3. 全局变量访问)
- 小结
嘿,前端开发小伙伴们!今天咱们来聊一聊Rollup这个有点低调但超级实用的JavaScript模块打包工具。说实话,在webpack一统江湖的年代,Rollup这样的工具往往被很多人忽略了。但它绝对是个宝藏工具,尤其是对于库的开发者来说简直是福音!
什么是Rollup?为啥要学它?
Rollup是一个JavaScript模块打包器,专注于ES模块(ESM)的处理。它于2015年由Rich Harris(没错,就是Svelte的创造者!)开发,主打简洁高效。
你可能会问:"都有webpack了,为啥还要学Rollup?"(我刚开始也是这么想的...)
几个超级吸引人的原因:
- 代码精简 - Rollup生成的包体积小,这是因为它有个杀手锏功能------Tree Shaking!它能自动移除未使用的代码。
- 适合库开发 - 如果你在开发一个JavaScript库,Rollup绝对是首选(Vue、React、Three.js等都在用它)。
- 配置简单 - 相比webpack复杂的配置,Rollup配置文件简单易懂,新手友好!
- 输出格式灵活 - 支持多种模块格式,包括ESM、CommonJS、UMD等。
总之,如果你厌倦了webpack的复杂配置,或者正准备开发一个库,是时候了解一下Rollup了!
开始使用Rollup
安装
首先,我们需要安装Rollup。可以全局安装或者作为项目依赖安装:
bash
# 全局安装
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
中,我们定义一些简单的计算函数:
javascript
// 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
中引入并使用这些函数:
javascript
// 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
};
}
注意看,我们只导入了add
和multiply
函数,没有用到subtract
和divide
。这就是Tree Shaking大显身手的地方!
接下来,创建一个Rollup配置文件rollup.config.js
:
javascript
// rollup.config.js
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'cjs' // CommonJS格式
}
};
这个配置文件超级简单:
input
: 入口文件output
: 输出配置file
: 输出文件路径format
: 输出格式(这里用的是CommonJS)
最后,在package.json
中添加构建脚本:
json
{
"name": "my-rollup-project",
"version": "1.0.0",
"scripts": {
"build": "rollup -c"
},
"devDependencies": {
"rollup": "^3.20.0"
}
}
运行构建命令:
bash
npm run build
完成后,查看生成的dist/bundle.js
文件,你会发现它只包含了我们实际使用的add
和multiply
函数,subtract
和divide
函数被自动移除了!这就是Tree Shaking的魔力!
输出格式
Rollup支持多种输出格式,适应不同的使用场景:
- esm/es: ES模块格式,现代浏览器原生支持
- cjs: CommonJS格式,适用于Node.js环境
- umd: 通用模块定义,同时支持浏览器和Node.js
- iife : 立即执行函数,适合作为
<script>
直接在浏览器中使用
修改配置文件以输出多种格式:
javascript
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中引入第三方模块。
bash
npm install --save-dev @rollup/plugin-node-resolve
修改配置文件:
javascript
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就能处理它们了。
bash
npm install --save-dev @rollup/plugin-commonjs
修改配置文件:
javascript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
// ...
plugins: [
resolve(),
commonjs()
]
};
3. @rollup/plugin-babel
如果你需要使用Babel来转换代码(比如使用最新的JavaScript特性),可以使用这个插件:
bash
npm install --save-dev @rollup/plugin-babel @babel/core @babel/preset-env
创建Babel配置文件.babelrc
:
json
{
"presets": [["@babel/preset-env", { "modules": false }]]
}
修改Rollup配置:
javascript
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
对打包后的代码进行压缩:
bash
npm install --save-dev @rollup/plugin-terser
修改配置:
javascript
import terser from '@rollup/plugin-terser';
export default {
// ...
plugins: [
// ...其他插件
terser()
]
};
实际项目配置示例
下面是一个较为完整的Rollup配置,包含了开发库时常用的设置:
javascript
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
配置:
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的情况:
- 开发JavaScript库或组件 - Rollup的Tree Shaking和干净的输出使其成为库开发的理想选择。
- 代码体积敏感 - 如果你需要最小化的输出体积。
- 配置简单 - 如果你厌倦了复杂的webpack配置。
- 项目结构简单 - 主要处理JavaScript模块,没有复杂的资源需求。
选择Webpack的情况:
- 开发应用程序 - 特别是有大量静态资源的复杂应用。
- 需要代码分割和动态导入 - Webpack在这方面更成熟。
- 需要处理多种资源 - 图片、CSS、字体等各种资源。
- HMR需求 - 热模块替换在开发体验上很重要。
个人经验:我会在开发库时使用Rollup,开发应用时使用Webpack或Vite(基于Rollup但针对应用开发优化)。
进阶技巧
1. 外部依赖
开发库时,你通常不想将所有依赖都打包进去。可以使用external
选项标记外部依赖:
javascript
export default {
// ...
external: ['lodash', 'react'],
// ...
};
这样,这些依赖将不会被打包,而是作为引用保留在代码中。
2. Sourcemaps
为了方便调试,可以生成sourcemaps:
javascript
export default {
// ...
output: {
// ...
sourcemap: true
}
};
3. 动态导入
Rollup支持代码分割和动态导入:
javascript
// 动态导入示例
import('./modules/heavy-module.js').then(module => {
// 使用模块
});
配置中需要指定代码分割的输出目录:
javascript
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构建中,如果你需要访问全局变量(如window
或document
),可以使用globals
选项:
javascript
export default {
// ...
output: {
// ...
format: 'umd',
globals: {
jquery: '$' // 将jquery映射到全局变量$
}
},
external: ['jquery'] // 标记jquery为外部依赖
};
小结
Rollup虽然没有Webpack那么出名,但它在JavaScript库开发领域绝对是一把利器!它的配置简单、输出干净、Tree Shaking出色,非常值得学习和使用。
如果你正在考虑开发一个JavaScript库,或者只是想尝试一个更轻量级的打包工具,绝对值得给Rollup一个机会!
最后,如果你已经习惯了Webpack,也不必急着完全迁移。两者可以共存,在适合的场景使用适合的工具。
希望这篇教程对你有所帮助!祝你编码愉快!