Rollup 常用插件
🎯 引言
学完这篇文章,你将掌握 Rollup 最常用的四个官方插件,能够解析第三方依赖、转换 CommonJS 模块、导入 JSON 文件,并对产物进行压缩。
🧱 为什么需要插件
Rollup 的核心非常纯粹:只认识写在项目里的 ES 模块。
但实际开发中,你经常会遇到这些情况:
import { debounce } from 'lodash-es'—— 依赖在node_modules里;- 某个老包是 CommonJS 写的,只有
module.exports; - 想直接
import info from './package.json'读取版本号; - 发布前想把代码压缩成一行。
这些需求都靠插件解决。Rollup 官方维护了一批高质量插件,名字统一以 @rollup/plugin- 开头。
本课程环境使用 Node.js v22.0.0,对应插件版本如下:
npm install @rollup/plugin-node-resolve@16.0.3 @rollup/plugin-commonjs@29.0.3 @rollup/plugin-json@6.1.0 @rollup/plugin-terser@1.0.0 --save-dev
下面逐个来看它们的用法。
🧰 node-resolve:解析第三方依赖
先看一个容易让人困惑的问题:明明已经 npm install lodash-es 了,为什么 Rollup 还是“找不到”它?
关键在于:npm install 只负责把文件下载到 node_modules 目录,而 Rollup 核心并不认识 node_modules 的查找规则。你的代码里其实有两种 import,走的是两套完全不同的规则:
// ① 相对路径:Rollup 核心认识,从当前文件出发直接就能找到
import { add } from './math.js';
// ② 裸导入(bare specifier):只是一个包名,没有路径信息,Rollup 核心不认识
import { debounce } from 'lodash-es';
第②种写法要找到真正的文件,需要一套专门的查找算法:
- 到
node_modules里定位lodash-es目录; - 读取它的
package.json,根据main/module/exports字段判断入口文件是哪个(包里有几百个文件,到底加载哪一个?); - 最终定位到具体文件,例如
node_modules/lodash-es/lodash.js。
这套规则叫 Node.js 模块解析算法,Node.js 运行时内置了它,但 Rollup 核心刻意没有内置——保持核心精简,也因为 Rollup 的设计初衷是打包库,默认假定依赖是外部提供的。node-resolve 插件的作用,就是把这套查找算法补进 Rollup:
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'es'
},
plugins: [resolve()]
};
加上它之后,lodash-es 就会被正常打进产物里。
(!) Unresolved dependencies 警告,并把 'lodash-es' 当作外部依赖原样保留在产物里。这样的产物在浏览器里运行会直接失败,因为浏览器同样不认识裸导入。所以只要引用了第三方包,记得加上 resolve()。🧰 commonjs:转换 CommonJS 模块
npm 上很多老牌包是用 CommonJS 写的(module.exports = ...)。Rollup 只懂 ES 模块,遇到它们会报错。
commonjs 插件负责把 CommonJS 模块转换成 ES 模块:
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'es'
},
plugins: [resolve(), commonjs()]
};
commonjs 必须写在 resolve()后面。Rollup 按数组顺序执行插件,得先找到文件,才能转换它。顺序写反是新手最常踩的坑。🧰 json:导入 JSON 文件
想在代码里直接读取 JSON 文件(比如 package.json 里的版本号),就用 json 插件:
import json from '@rollup/plugin-json';
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'es'
},
plugins: [json()]
};
之后就可以像导入模块一样导入 JSON:
import pkg from '../package.json';
export function getVersion() {
return pkg.version;
}
打包后 JSON 内容会变成普通的 JavaScript 对象,嵌进产物里。
package.json 有几十个字段,但你只用了 version,产物里就只会包含 version,其余字段会被 Tree Shaking 移除。🧰 terser:压缩代码
发布前通常要把代码压缩,去掉空格注释、缩短变量名。terser 插件就是干这个的,它的用法比较特殊——写在 output.plugins 里,而不是顶层的 plugins:
import terser from '@rollup/plugin-terser';
export default {
input: 'src/index.js',
output: [
{
file: 'dist/bundle.js',
format: 'es'
},
{
file: 'dist/bundle.min.js',
format: 'es',
plugins: [terser()]
}
]
};
这样配置后会同时得到两份产物:一份正常代码(方便调试),一份压缩代码(发布给用户)。
压缩前后的对比非常明显:
function add(a, b) {
return a + b;
}
export { add };
function n(n,t){return n+t}export{n as add};
output.plugins?因为压缩发生在“产物生成之后”,属于输出阶段的操作。写在顶层 plugins 里虽然也能生效,但写在 output 里可以精确控制只压缩某一份产物。🧾 小节总结
- Rollup 核心只认 ES 模块,其余能力靠插件扩展,官方插件以
@rollup/plugin-开头。 node-resolve解析node_modules依赖,commonjs转换 CommonJS 模块,二者通常搭配使用且resolve在前。json插件支持直接importJSON 文件,未用到的字段会被摇掉。terser用于压缩代码,推荐写在output.plugins中,按产物分别控制。
❓ 知识问答
Q1:我已经 npm install 了,为什么打包时提示 Unresolved dependencies?
A:安装只是把文件放进了 node_modules,但 Rollup 核心不认识裸导入的查找规则,需要 node-resolve 插件来补这套算法。找到警告后,在 plugins 里加上 resolve() 即可。
Q2:所有第三方包都需要 commonjs 插件吗?
A:不是。现在越来越多的包直接提供 ES 模块版本(如 lodash-es),这种只需要 node-resolve。只有引用纯 CommonJS 的老包时才需要 commonjs。
Q3:插件的执行顺序一定是从左到右吗?
A:是的。plugins 数组决定了执行顺序,记住口诀:先找到(resolve)、再转换(commonjs)、其他插件随后。
Q4:压缩后的代码出错了好调试吗?
A:直接调试很困难,因为变量名都被缩短了。这就是上一篇讲的 sourcemap 的用武之地,配合 .map 文件就能映射回源码。
Q5:Rollup 有没有处理 CSS、图片的插件?
A:有,社区提供了 rollup-plugin-postcss、@rollup/plugin-image 等插件。但写 JavaScript 库时很少用到,了解即可。
🧪 小练习
给 rollup-demo 加上插件支持:
- 安装本篇文章提到的四个插件(版本见文章开头的安装命令)。
- 在
src/index.js中导入../package.json并导出一个getName函数返回包名。 - 配置
rollup.config.mjs,输出一份正常文件和一份.min.js压缩文件。
import json from '@rollup/plugin-json';
import terser from '@rollup/plugin-terser';
export default {
input: 'src/index.js',
output: [
{
file: 'dist/bundle.js',
format: 'es'
}
// 请在这里补充 bundle.min.js 压缩产物
],
plugins: [json()]
};
🎉 恭喜你已经掌握了 Rollup 的常用插件!下一篇我们会深入 Rollup 的招牌能力——Tree Shaking。
