Rollup 简介

输出格式:ESM、CJS 与 UMD

理解 Rollup 的四种输出格式及其适用场景,学会一次打包输出多种格式。

🎯 引言

学完这篇文章,你将理解 escjsumdiife 四种输出格式的区别,知道什么环境该选哪种格式,并能一次打包同时输出多份产物。


🧱 为什么需要输出格式

你写的库会被别人在各种环境里使用:

  • 有人在 Vite / Webpack 项目里 import 它;
  • 有人在 Node.js 老项目里 require 它;
  • 还有人直接在浏览器里用 <script> 标签引入它。

这些环境“说”的模块语言不一样,所以 Rollup 提供了 output.format 选项,把同一份源码翻译成不同的模块格式。


⚡ 四种常用格式对比

格式全称适用环境典型用法
esES Module现代浏览器、打包工具import { add } from 'my-utils'
cjsCommonJSNode.js 传统环境const { add } = require('my-utils')
umdUniversal Module Definition浏览器 + Node.js 通吃<script> 标签引入
iifeImmediately Invoked Function Expression纯浏览器<script> 标签引入,立即执行

简单记忆:

  • 写库给别人用:至少输出 es + cjs,照顾打包工具和 Node.js。
  • 直接在浏览器用:输出 umdiife
umdiife 都能给浏览器用,区别在于 umd 同时兼容 Node.js 和 AMD 环境,而 iife 只在浏览器里跑。拿不准就选 umd

🛠 一次输出多种格式

output 可以写成数组,一次打包生成多份产物:

rollup.config.mjs
export default {
    input: 'src/index.js',
    output: [
        {
            file: 'dist/bundle.esm.js',
            format: 'es'
        },
        {
            file: 'dist/bundle.cjs.js',
            format: 'cjs'
        },
        {
            file: 'dist/bundle.umd.js',
            format: 'umd',
            name: 'MyUtils'
        }
    ]
};

执行 npm run build 后,dist 目录下会同时生成三个文件,分别对应三种环境。

注意 umdiife 格式必须配置 name,它是暴露给浏览器的全局变量名。比如上面配置 name: 'MyUtils' 后,浏览器里就能通过 window.MyUtils.add(1, 2) 调用你的函数。漏掉它会直接报错。

💡 三种格式的产物长什么样

同一份源码,三种格式的产物风格差异很大,看一眼就有直观感受。

ES 格式几乎就是源码原样合并,export 保留:

dist/bundle.esm.js
function add(a, b) {
    return a + b;
}

export { add };

CJS 格式export 转成了 Node.js 认识的 exports

dist/bundle.cjs.js
'use strict';

function add(a, b) {
    return a + b;
}

exports.add = add;

UMD 格式外面包了一层环境判断,自动适配不同环境:

dist/bundle.umd.js
(function (global, factory) {
    // 判断当前是 Node.js、AMD 还是浏览器,选择对应的导出方式
    typeof exports === 'object' && typeof module !== 'undefined'
        ? factory(exports)
        : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.MyUtils = {})));
})(this, function (exports) {
    'use strict';
    // ...
});

UMD 看起来复杂,但你不用手写,Rollup 会自动生成。


🧾 小节总结

  • 不同环境使用不同的模块格式,Rollup 用 output.format 控制产物格式。
  • es 给打包工具和现代浏览器,cjs 给 Node.js,umd / iife 给浏览器直接引用。
  • output 写成数组可以一次输出多份产物。
  • umdiife 格式必须配置 name,作为浏览器的全局变量名。

❓ 知识问答

Q1:我的库只用在新项目里,可以只输出 es 格式吗?

A:可以。如果确定使用方都会通过 Vite / Webpack 引入,只输出 es 最简单。开源库为了兼容性一般会同时提供 cjs

Q2:format: 'es'format: 'esm' 有区别吗?

A:没有区别,esmes 的别名,写哪个都行。同理 cjs 也可以写成 commonjs

Q3:UMD 的 name 可以带横线吗,比如 my-utils

A:不建议。name 会变成全局变量名,必须是一个合法的 JavaScript 标识符,推荐用大驼峰写法,如 MyUtils

Q4:输出多种格式会让打包变慢吗?

A:会略微变慢,因为要写多份文件。但 Rollup 的依赖分析只做一次,实际影响很小,可以放心使用。


🧪 小练习

改造 rollup-demo 项目的配置,一次输出两种格式:

  1. output 数组中添加 escjs 两份输出,文件名分别为 bundle.esm.jsbundle.cjs.js
  2. 执行 npm run build,对比两份产物中 export 的写法差异。
rollup.config.mjs
export default {
    input: 'src/index.js',
    output: [
        {
            file: 'dist/bundle.esm.js',
            format: 'es'
        }
        // 请在这里补充 cjs 格式的输出
    ]
};

🎉 恭喜你已经掌握了 Rollup 的输出格式!下一篇我们会学习插件系统,让 Rollup 能处理 JSON 文件和第三方依赖。