Rollup 简介

实战:打包并发布一个工具库

综合运用前面所学,用 Rollup 打包一个工具库:external 外部依赖、多格式产物、package.json 发布配置。

🎯 引言

学完这篇文章,你将把前面五篇的知识串起来,用 Rollup 完整地打包一个可以发布到 npm 的工具库,包括外部依赖处理、多格式产物和发布配置。


🧱 目标:把工具函数发布出去

假设我们写了一个工具库 my-utils,源码如下:

src/index.js
import { debounce } from 'lodash-es';

export function formatPrice(num) {
    return '¥' + Number(num).toFixed(2);
}

export { debounce };

我们的目标是:

  1. 产出 escjs 两种格式,适配不同环境。
  2. 额外提供一份压缩版本。
  3. 配置好 package.json,让别人 npm install 后能直接使用。

🛠 第一步:external 排除第三方依赖

先看一个关键问题:lodash-es 应该打进产物里吗?

不应该。因为使用方安装你的库时,npm 会自动帮你安装 lodash-es,没必要在你的产物里再塞一份,否则同一份代码就被打包了两次。

external 选项告诉 Rollup:“这些依赖是外部提供的,不要打进来”:

rollup.config.mjs
export default {
    input: 'src/index.js',
    external: ['lodash-es'],
    output: {
        file: 'dist/my-utils.esm.js',
        format: 'es'
    }
};

打包后的产物里,import 语句被原样保留:

dist/my-utils.esm.js
export { debounce } from 'lodash-es';

function formatPrice(num) {
    return '¥' + Number(num).toFixed(2);
}

export { formatPrice };
凡是在 package.jsondependencies 里声明的依赖,都应该加入 external。只有你自己的源码才需要打包。

🛠 第二步:多格式输出 + 压缩版本

把前面学过的多格式输出和 terser 压缩组合起来,形成最终配置:

rollup.config.mjs
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 中配置三个字段:

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 课程中有详细介绍)。


💡 完整回顾:一条标准的库打包流程

到这里,我们可以总结出一个工具库的标准工作流:

  1. 用 ES 模块写源码,import / export 写清楚。
  2. 第三方依赖加入 external,并声明到 dependencies
  3. 输出 es + cjs 双格式,必要时加一份压缩产物。
  4. package.json 配好 mainmodulefiles
  5. 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 改造成一个可发布的库:

  1. src/index.js 中导出 formatPrice 和从 lodash-es 转出的 debounce
  2. 参照本篇配置 rollup.config.mjs,输出三份产物。
  3. 补全 package.jsonmainmodulefiles 字段。
package.json
{
    "name": "my-utils",
    "version": "1.0.0",
    "main": "dist/my-utils.cjs.js",
    "module": "dist/my-utils.esm.js"
    // 请在这里补充 files 字段
}

🎉 恭喜你已经掌握了 Rollup 的核心技能!从第一个打包示例到发布完整的工具库,你已经具备了独立构建 JavaScript 库的能力。试着把自己常用的工具函数封装成库,发布到 npm 上吧!