Rollup 更适合做工具库、组件库的产物构建,适合追求输出精简,格式多样,可控性强的前端开发需求。
但是对于想做Web应用开发的,则不是很合适,Vite、Webpack、Rsbuild或许是更好的选择
一、常见打包格式
1.1 IIFE (Immediately Invoked Function Expression) 立即执行函数表达式
IIFE是最适合直接在浏览器<script>标签引用的格式,也是曾经被广泛使用的格式
整个代码被包在一个自调用函数里,从而保证不向全局变量泄露内部变量,导致全局变量被污染
(function () {
const msg = "Hello IIFE";
console.log(msg);
})();
1.2 ESM (ES Modules 模块)
ESM是现代JavaScript 官方模块,在没有ESM的时代,JavaScript 主要靠 CommonJS (Node) + Browserify/Webpack 和 AMD (RequireJS)来实现模块化和打包
ESM 支持静态分析、tree-shaking,是目前主流的打包格式
// math.js
export const add = (a, b) => a + b;
// main.js
import { add } from './math.js';
console.log(add(1, 2));
浏览器原生支持:
<script type="module">
import { add } from './math.js';
console.log(add(2, 3));
</script>
1.3 CJS (CommonJS) Node.js 的经典模块格式
在还没有ESM的时候,Node.js 自己实现的一种模块格式,他是一种同步导入模块的方式
你甚至可以直接从 node_modules 中引入一个库或者文本目录引入一个文件,都是支持的比如:const myLocalModule = require('./some/local/file.js') 或者是 var React = require('react'); 都是有效的写法
这种格式不支持直接在浏览器中运行
// importing
const doSomething = require('./doSomething.js');
// exporting
module.exports = function doSomething(n) {
// do something
}
❌ require 动态加载无法静态分析 → 无法 tree-shaking
1.4 UMD (Universal Module Definition) 通用格式
UMD 兼容 IIFE + CJS + AMD 模块系统
设计出来就是想一个文件可以在各种环境运行 - 浏览器、Node、RequireJS 都可以通用
(function (root, factory) {
if (typeof exports === 'object' && typeof module === 'object')
module.exports = factory(); // Node (CJS)
else if (typeof define === 'function' && define.amd)
define([], factory); // AMD
else
root.MyLib = factory(); // 浏览器全局
})(this, function () {
return {
add(a, b) { return a + b; }
};
});
浏览器用:
<script src="mylib.umd.js"></script>
<script>
console.log(MyLib.add(1, 2));
</script>
Node 用:
const MyLib = require('./mylib.umd.js');
| 特性 | 说明 |
|---|---|
| ✅ 通用性最强,浏览器+Node 都能直接用 | |
| ✅ 适合发 npm 包兼容老生态 | |
| ❌ 文件较大,结构复杂 | |
| ❌ 不具备 ESM 的 tree-shaking 优势 |
二、简单例子,上手rollup基础配置
从一个简单的例子开始上手
2.1 安装
初始化一个项目以后,在项目中安装包
npm install -D rollup
2.2 配置、代码
一个最基础的配置,同时打包出 esm、cjs、umd
export default {
input: 'src/index.js',
output: [
{ file: 'dist/index.esm.js', format: 'esm' },
{ file: 'dist/index.cjs.js', format: 'cjs' },
{ file: 'dist/index.umd.js', format: 'umd', name: 'MyLib' },
]
}
写一个简单的例子:
// add.js
export function add(a, b) {
return a + b;
}
// main.js
import { add } from './add';
console.log(add(1, 2));
配置一下package.json 增加一个build参数
{
"name": "rollup-pack-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "rollup -c rollup.config.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"rollup": "^4.52.5"
}
}
打包命令:
npm run build
输出打包后的单文件,浏览器、Node 都能直接用,打包产物如下

三、如何引入TypeScript ?
3.1 新建项目与安装
# 1) 新建目录与初始化
mkdir my-lib && cd my-lib
npm init -y
# 2) 安装 rollup 与常用插件
npm i -D rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-json
# 3) 压缩与环境变量替换(可选)
npm i -D @rollup/plugin-terser @rollup/plugin-replace
# 4) TypeScript 支持(后文用到)
npm i -D typescript @rollup/plugin-typescript rollup-plugin-dts
# 5) 类型检查/声明生成(可选但强烈建议)
npx tsc --init
目录建议:
my-lib/
├─ src/
│ └─ index.ts # 入口(JS 项目可用 .js)
├─ rollup.config.mjs # Rollup 配置(ESM)
├─ package.json
└─ tsconfig.json
3.2 基础配置
tsconfig.json 配置,支持TypeScript
{
"compilerOptions": {
"module": "ESNext", // 让 TS 仅做类型检查与转译协作
"target": "ES2020",
"types": [],
"sourceMap": true,
"moduleResolution": "Bundler", // 与 Rollup 更匹配(或 "NodeNext")
"declaration": true, // 生成 .d.ts
"declarationMap": true,
"emitDeclarationOnly": false, // 由 Rollup 统一产物(dts 另见下节)
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"strict": true,
"jsx": "react-jsx",
"verbatimModuleSyntax": true,
"isolatedModules": true,
"noUncheckedSideEffectImports": true,
"moduleDetection": "force",
"skipLibCheck": true,
"paths": {
"@/*": [
"./src/*"
]
}
},
"baseUrl": ".",
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}
源码:src/index.ts
import { add } from '@/add';
console.log(add(1, 2));
源代码:src/add.ts
export function add(a: number, b: number) {
return a + b;
}
还需要配置一下rollup来支持typeScript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import replace from '@rollup/plugin-replace';
import terser from '@rollup/plugin-terser';
import typescript from '@rollup/plugin-typescript';
import dts from 'rollup-plugin-dts';
const isProd = process.env.NODE_ENV === 'production';
// 主构建(js)
const main = {
input: 'src/index.ts',
external: [], // 如 ['react']
plugins: [
resolve({ extensions: ['.mjs', '.js', '.json', '.ts'] }),
commonjs(),
json(),
replace({
preventAssignment: true,
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
}),
typescript({
tsconfig: './tsconfig.json',
declaration: false, // 由 dts 插件单独处理
outDir: undefined
}),
isProd && terser(),
],
output: [
{ file: 'dist/index.esm.js', format: 'esm', sourcemap: true },
{ file: 'dist/index.cjs.js', format: 'cjs', sourcemap: true },
{ file: 'dist/index.umd.js', format: 'umd', name: 'MyLib', sourcemap: true }
]
};
// 类型声明打包(.d.ts)
const types = {
input: 'dist/types/src/index.d.ts', // 由 tsc 先产出到 dist/types
output: [{ file: 'dist/index.d.ts', format: 'es' }],
plugins: [dts()],
};
// 默认导出数组可以同时执行多任务构建
export default [main, types];
这个配置主要做两件事
- 把TS源代码变异成JS产物,分别输出 ESM、CJS、UMD
- 把 TypeScript
.d.ts类型声明拆开产出的碎文件合并成一个- 最终得到
dist/index.d.ts
- 最终得到
external 参数作用
external: ['react', 'react-dom']
指定哪些依赖不打入产物。例如如果你的库依赖 React,填进去以后就不会将react打包进bundle,这样做,打包出来的体积会更小
plugin 说明
plugins: [
resolve({ extensions: ['.mjs', '.js', '.json', '.ts'] }),
commonjs(),
json(),
replace({
preventAssignment: true,
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
}),
typescript({
tsconfig: './tsconfig.json',
declaration: false, // 由 dts 插件单独处理
outDir: undefined
}),
isProd && terser(),
]
- resolve: 识别 node 模块、拓展名
- commonjs: 转换 CommonJS 模块
- json:支持JSON导入
- typescript: 处理typescript文件

暂无评论