实战:打包并发布一个工具库
🎯 引言
学完这篇文章,你将把前面五篇的知识串起来,用 Rollup 完整地打包一个可以发布到 npm 的工具库,包括外部依赖处理、多格式产物和发布配置。
🧱 目标:把工具函数发布出去
假设我们写了一个工具库 my-utils,源码如下:
import { debounce } from 'lodash-es';
export function formatPrice(num) {
return '¥' + Number(num).toFixed(2);
}
export { debounce };
我们的目标是:
- 产出
es和cjs两种格式,适配不同环境。 - 额外提供一份压缩版本。
- 配置好
package.json,让别人npm install后能直接使用。
🛠 第一步:external 排除第三方依赖
先看一个关键问题:lodash-es 应该打进产物里吗?
不应该。因为使用方安装你的库时,npm 会自动帮你安装 lodash-es,没必要在你的产物里再塞一份,否则同一份代码就被打包了两次。
用 external 选项告诉 Rollup:“这些依赖是外部提供的,不要打进来”:
export default {
input: 'src/index.js',
external: ['lodash-es'],
output: {
file: 'dist/my-utils.esm.js',
format: 'es'
}
};
打包后的产物里,import 语句被原样保留:
export { debounce } from 'lodash-es';
function formatPrice(num) {
return '¥' + Number(num).toFixed(2);
}
export { formatPrice };
package.json 的 dependencies 里声明的依赖,都应该加入 external。只有你自己的源码才需要打包。🛠 第二步:多格式输出 + 压缩版本
把前面学过的多格式输出和 terser 压缩组合起来,形成最终配置:
import resolve from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
export default {
input: 'src/index.js',
external: ['lodash-es'],
output: [
{
file: 'dist/my-utils.esm.js',
format: 'es'
},
{
file: 'dist/my-utils.cjs.js',
format: 'cjs'
},
{
file: 'dist/my-utils.esm.min.js',
format: 'es',
plugins: [terser()]
}
],
plugins: [resolve()]
};
执行 npm run build,一次得到三份产物:
| 产物 | 用途 |
|---|---|
my-utils.esm.js | 给 Vite / Webpack 等打包工具使用,支持 Tree Shaking |
my-utils.cjs.js | 给 Node.js 传统环境使用 |
my-utils.esm.min.js | 压缩版本,体积最小 |
📦 第三步:配置 package.json
产物有了,还需要告诉 npm:“不同环境应该加载哪个文件”。在 package.json 中配置三个字段:
{
"name": "my-utils",
"version": "1.0.0",
"main": "dist/my-utils.cjs.js",
"module": "dist/my-utils.esm.js",
"files": ["dist"],
"scripts": {
"build": "rollup -c"
},
"dependencies": {
"lodash-es": "^4.17.21"
}
}
三个新字段的含义:
main:CommonJS 环境的入口,require('my-utils')时加载它。module:ES 模块环境的入口,打包工具import时优先加载它,从而支持 Tree Shaking。files:发布到 npm 时只包含dist目录,源码和配置文件不会上传,包体积更小。
lodash-es 写进 dependencies 而不是 devDependencies。使用方安装你的库时,npm 只会自动安装 dependencies 里的包。配置完成后,就可以执行 npm publish 把库发布出去了(发布流程在 NPM 课程中有详细介绍)。
💡 完整回顾:一条标准的库打包流程
到这里,我们可以总结出一个工具库的标准工作流:
- 用 ES 模块写源码,
import/export写清楚。 - 第三方依赖加入
external,并声明到dependencies。 - 输出
es+cjs双格式,必要时加一份压缩产物。 package.json配好main、module、files。npm run build构建,npm publish发布。
这套流程正是 Vue、React 等开源库的日常发布方式,你已经掌握了它的核心。
🧾 小节总结
- 第三方依赖用
external排除,避免重复打包,同时声明进dependencies。 - 标准产物组合:
es+cjs双格式,再加一份 terser 压缩版本。 package.json通过main/module指向不同格式的入口,files控制发布内容。- 写库选 Rollup、依赖用 ES 模块、配好双格式入口,就是一个对使用方友好的现代工具库。
❓ 知识问答
Q1:external 可以写成函数或正则吗?
A:可以。依赖很多时可以写正则,比如 external: [/^lodash/] 匹配所有 lodash 开头的包。依赖少时直接列字符串数组更清晰。
Q2:为什么不直接给浏览器输出一份 UMD?
A:现在通过 <script> 标签直接引用的场景越来越少,大部分用户都通过打包工具使用库。如果确实有需求,按第三篇的方法加一份 umd 产物并配置 name 即可。
Q3:源码需要一起发布吗?
A:一般不需要。files: ["dist"] 只发布产物即可。有些库会额外发布源码方便调试,但不是必须的。
Q4:每次发布前都要手动执行 npm run build 吗?
A:可以在 package.json 里加 "prepublishOnly": "npm run build",这样执行 npm publish 时会自动先构建,防止发布旧产物。
🧪 小练习
把 rollup-demo 改造成一个可发布的库:
- 在
src/index.js中导出formatPrice和从lodash-es转出的debounce。 - 参照本篇配置
rollup.config.mjs,输出三份产物。 - 补全
package.json的main、module、files字段。
{
"name": "my-utils",
"version": "1.0.0",
"main": "dist/my-utils.cjs.js",
"module": "dist/my-utils.esm.js"
// 请在这里补充 files 字段
}
🎉 恭喜你已经掌握了 Rollup 的核心技能!从第一个打包示例到发布完整的工具库,你已经具备了独立构建 JavaScript 库的能力。试着把自己常用的工具函数封装成库,发布到 npm 上吧!
