unbuild
UnJS 生态的统一 JavaScript/TypeScript 库构建系统,基于 Rollup + esbuild,零配置打包,Monorepo 友好。
unbuild 是 UnJS 生态的统一库构建系统,底层结合 Rollup 生产级打包和 esbuild 高速转译,独创 Stub 模式实现 Monorepo 零重建开发,自动从 package.json 推断构建配置。
unbuild
UnJS 生态的统一 JavaScript/TypeScript 库构建系统,基于 Rollup + esbuild,零配置打包,Monorepo 友好。
技术简介说明
unbuild 是由 UnJS 团队开发的统一 JavaScript 构建系统,定位为面向库作者和 Monorepo 场景的零配置打包工具。它底层基于 Rollup 进行生产级捆绑优化,同时借助 esbuild 实现高速 TypeScript 转译,兼顾了产物质量和构建速度。unbuild 广泛应用于 Nuxt、Nitro、UnJS 全家桶等知名项目的构建流程中,是 UnJS 生态的核心基础设施之一。
unbuild 的核心价值在于"约定优于配置"和"开发体验优先"。它能自动从 package.json 的 exports 字段推断构建入口和输出格式,绝大多数场景下无需编写额外配置文件。同时它独创了 Stub(插桩)模式——利用 jiti 生成轻量代理文件,将 dist 产物直接映射到源码,使 Monorepo 中的包在开发阶段无需重复构建即可热更新,被社区称为"Monorepo 杀手级特性"。
自 2021 年发布以来,unbuild 经历了从 v1 到 v3 的持续迭代,截至 2026 年 7 月最新稳定版为 v3.6.1。UnJS 团队还在实验基于 Rolldown(Rust 实现)的下一代继任者 obuild,以追求更快的构建速度。unbuild 在 npm 上月下载量超过 32 万次,GitHub 超过 2700 星,是 TypeScript 库构建工具领域的重要选择之一。
基本信息
- 官网:https://unjs.io/packages/unbuild
- GitHub:https://github.com/unjs/unbuild
- License:MIT
- 最新版本:v3.6.1(2025 年 8 月 15 日发布)
- 主要维护者/公司:UnJS 团队(核心维护者 Pooya Parsa @pi0、Daniel Roe @danielroe、Julien Huang @huang-julien),Nuxt/UnJS 生态
快速上手
安装
# 使用 npm
npm install unbuild -D
# 使用 pnpm
pnpm add unbuild -D
# 使用 yarn
yarn add unbuild -D
# 直接执行(无需安装)
npx unbuild基础配置
unbuild 支持零配置启动,但也可通过配置文件进行精细控制。
方式一:package.json 中配置(零配置推荐)
{
"name": "my-lib",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": ["dist"],
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub"
}
}unbuild 会自动从 package.json 的 exports、main、types 字段推断入口和输出格式。
方式二:build.config.ts 配置文件
支持的文件名格式:build.config.{js,cjs,mjs,ts,mts,cts,json}
// build.config.ts
import { defineBuildConfig } from 'unbuild'
export default defineBuildConfig({
// 构建入口(默认 ['./src/index'])
entries: [
'src/index', // 简写形式
{ input: 'src/cli/', builder: 'mkdist' }, // bundleless 模式
{ input: 'src/components/', builder: 'mkdist', declaration: true },
],
// 输出目录(默认 'dist')
outDir: 'dist',
// 类型声明生成:true | 'compatible' | 'node16' | false | undefined(自动检测)
declaration: 'compatible',
// 生成 Source Map
sourcemap: true,
// 外部依赖(不打包进产物)
externals: ['lodash', 'vue'],
// Rollup 配置
rollup: {
emitCJS: true, // 同时输出 CJS 格式
inlineDependencies: false,
esbuild: {
target: 'es2020',
minify: true,
// tsconfigRaw: {
// compilerOptions: { experimentalDecorators: true }
// }
},
replace: {
__VERSION__: '"1.0.0"',
},
},
// 生命周期钩子
hooks: {
'build:prepare': (ctx) => { /* 构建准备阶段 */ },
'build:done': (ctx) => { console.log('构建完成!') },
},
})最小示例
1. 创建源码文件:
// src/index.ts
export function greet(name: string): string {
return `Hello, ${name}!`
}
export const version = '1.0.0'2. 配置 package.json:
{
"name": "my-lib",
"version": "1.0.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
},
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub"
}
}3. 构建:
npx unbuild输出:
dist/
├── index.mjs # ESM 格式
├── index.cjs # CJS 格式
├── index.d.mts # ESM 类型声明
├── index.d.cts # CJS 类型声明
└── index.d.ts # 通用类型声明
核心概念与架构
双构建模式
unbuild 提供两种互补的构建模式,对应不同的使用场景:
| 模式 | Builder | 说明 |
|---|---|---|
| Bundled(捆绑) | rollup | 传统打包模式,将所有代码合并为优化后的 bundle,支持 tree-shaking、代码分割 |
| Bundleless(无捆绑) | mkdist | 逐文件转译模式,保持源码目录结构,类似 tsc 但更快 |
架构设计
┌──────────────────────────────────────────────────┐
│ build.config.ts │
│ (配置层 / defineBuildConfig) │
├──────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌──────────────────────┐ │
│ │ Rollup │ │ mkdist │ │
│ │ Builder │ │ (Bundleless) │ │
│ │ │ │ │ │
│ │ ┌────────┐ │ │ 文件到文件转译 │ │
│ │ │ esbuild│ │ │ 保持目录结构 │ │
│ │ │ (转译) │ │ │ 支持 Vue SFC │ │
│ │ └────────┘ │ │ 支持静态文件复制 │ │
│ └─────────────┘ └──────────────────────┘ │
│ │
│ ┌─────────────┐ ┌──────────────────────┐ │
│ │ jiti Stub │ │ untyped │ │
│ │ (开发模式) │ │ (类型生成) │ │
│ │ │ │ │ │
│ │ 代理文件 │ │ Markdown → 类型 │ │
│ │ 零重建开发 │ │ 配置对象 → 类型 │ │
│ └─────────────┘ └──────────────────────┘ │
│ │
├──────────────────────────────────────────────────┤
│ 输出: ESM + CJS + .d.ts + SourceMap │
└──────────────────────────────────────────────────┘
核心工作流程
- 配置解析:读取
build.config.ts或从package.json自动推断 - 入口发现:通过
entries配置或autoPreset扫描src/目录 - 构建执行:根据每个 entry 指定的 builder 分别执行(rollup 或 mkdist)
- 类型生成:通过 rollup-plugin-dts 或 mkdist 生成
.d.ts声明文件 - 产物输出:写入
outDir(默认dist/),输出大小和导出信息摘要
核心特性
- Rollup 驱动的生产级打包:基于 Rollup 的 tree-shaking 和代码分割能力,生成高质量的 ESM/CJS 产物,内置大量优质 Rollup 插件
- esbuild 高速转译:使用 esbuild 处理 TypeScript/ESNext 转译,比传统
rollup-plugin-typescript2快数十倍 - 零配置自动推断:自动从
package.json的exports/main/types字段推断构建入口、输出格式和类型声明配置 - Bundleless 构建(mkdist):集成 mkdist 实现逐文件转译,保持源码目录结构,支持 Vue SFC 组件和静态资源复制
- Stub 插桩模式:
unbuild --stub利用 jiti 生成轻量代理文件(50ms 内完成),将 dist 产物映射到源码,Monorepo 开发无需重复构建 - 多格式输出:同时输出 ESM(
.mjs)、CJS(.cjs)和多种类型声明(.d.ts/.d.mts/.d.cts),支持 Node16 和 Compatible 模式 - 安全构建检查:自动检测丢失或未使用的依赖项,CI 环境中自动报错,CLI 输出包含包大小和导出信息
- 生命周期钩子系统:提供
build:prepare、build:done等钩子,支持自定义构建逻辑扩展 - Preset 预设系统:支持可复用的预设配置,便于在多个项目间共享构建配置
- Source Map 支持:完整的 Source Map 生成能力,方便调试
生态图
UnJS 生态位置
unbuild 是 UnJS 生态的核心构建基础设施,UnJS 是一个提供高质量 Universal JavaScript 工具集开源组织,每月 npm 下载量超过 4.21 亿次。
UnJS 生态
├── Nuxt 3 — 全栈 Vue 框架(使用 unbuild 构建模块)
├── Nitro — 通用 HTTP 服务器引擎(使用 unbuild 构建)
├── unbuild ★ — 库构建系统(本文主题)
├── mkdist — Bundleless 文件转译器(unbuild 内置集成)
├── jiti — 运行时 TypeScript/ESM 执行器(Stub 模式核心)
├── untyped — 类型生成器(从配置生成 TypeScript 类型)
├── defu — 对象默认值合并(配置合并核心)
├── hookable — 异步钩子系统(生命周期管理)
├── unplugin — 统一插件系统(跨构建工具插件)
├── c12 / changelogen — 配置加载 / Changelog 生成
├── pkg-types — package.json / tsconfig.json 类型和工具
└── ...更多 60+ 包
关键依赖
| 依赖 | 作用 |
|---|---|
| Rollup | 生产级捆绑器核心 |
| esbuild | 高速 TypeScript/JS 转译 |
| rollup-plugin-dts | .d.ts 类型声明捆绑 |
| mkdist | Bundleless 文件到文件转译 |
| jiti | 运行时 TS/ESM 执行,Stub 模式核心 |
| untyped | 从配置生成 TypeScript 类型定义 |
| defu | 递归对象合并,用于配置解析 |
| hookable | 构建生命周期钩子管理 |
| magic-string | Source Map 字符串操作 |
| scule | 字符串工具(命名转换等) |
相关工具
- @nuxt/module-builder:Nuxt 模块构建器,本质是 unbuild 的预设封装
- obuild(实验性):基于 Rolldown 的下一代继任者,追求更快构建速度
- unplugin:统一插件系统,支持 Rollup/Vite/Webpack/esbuild 等多平台
适用场景
- TypeScript/JavaScript 库开发:unbuild 的主要使用场景,生成 ESM/CJS 双格式产物和类型声明,适合发布到 npm 的工具库和组件库
- Monorepo 多包开发:Stub 模式是核心优势,多个包之间互相链接时无需重复构建,源码修改即时生效,极大提升开发效率
- Nuxt 模块开发:通过
@nuxt/module-builder(unbuild 预设),是 Nuxt 模块的标准构建方式 - CLI 工具开发:对
package.json中的bin字段有特殊处理,自动处理 shebang 和可执行文件权限 - Vue 组件库构建:mkdist 模式支持 Vue SFC 单文件组件的逐文件转译,保持组件独立可引用
- UnJS 生态项目:所有 UnJS 系列包(unstorage、unctx、ohash 等)均使用 unbuild 构建
- 需要 Rollup 插件生态的场景:底层使用 Rollup,可以复用 Rollup 的丰富插件生态进行自定义构建逻辑
开发与工程化
开发流程
# 1. 开发模式(Stub 插桩,无需重建)
npx unbuild --stub
# 2. 生产构建
npx unbuild
# 3. 类型检查
npx tsc --noEmit
# 4. 本地测试
npm link # 或 pnpm link推荐的 package.json scripts
{
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub",
"prepack": "unbuild",
"lint": "eslint .",
"test": "vitest",
"typecheck": "tsc --noEmit"
}
}CI/CD 集成
# GitHub Actions 示例
name: CI & Release
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: corepack enable && pnpm install
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm build
- run: pnpm test
release:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
- run: corepack enable && pnpm install
- run: pnpm build
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}Monorepo 最佳实践
# Monorepo 根目录
packages/
├── core/ # 核心包(使用 unbuild)
│ ├── src/
│ ├── build.config.ts
│ └── package.json
├── utils/ # 工具包(使用 unbuild)
│ ├── src/
│ └── package.json
└── app/ # 消费应用
# 根目录开发流程
pnpm install
pnpm --filter ./packages/* exec unbuild --stub
# 所有包的 dist/ 现在指向源码,修改即时生效发布检查清单
- 运行
unbuild后检查 CLI 输出的包大小和导出信息 - 确认
dist/目录中包含.mjs、.cjs、.d.ts等所有预期产物 - 注意 unbuild 会自动检查缺失或未使用的依赖,CI 中会报错
- 使用
files字段限制发布文件,推荐["dist"]
性能与安全
性能特点
| 指标 | 数据 |
|---|---|
| 冷启动构建(50 文件) | ~3.4 秒 |
| Watch 模式更新 | ~280ms |
| Stub 插桩模式 | ~50ms |
- 生产构建使用 Rollup 保证产物质量和 tree-shaking,速度略慢于纯 esbuild 方案(如 tsup)
- Stub 模式极快(50ms),因为仅生成代理文件不做实际捆绑
- esbuild 处理转译,比传统 Rollup + TypeScript 插件方案快 10-30 倍
优化建议
- 启用 minify:
rollup.esbuild.minify: true减小产物体积 - 合理配置 externals:避免将大型依赖打包进产物
- 使用 mkdist 模式:对于组件库等不需要 tree-shaking 的场景,bundleless 模式更快
- 启用 Stub 开发:
unbuild --stub避免开发时反复构建 - 使用
rollup.replace:编译期注入常量,避免运行时开销
安全注意事项
- unbuild 内置依赖检查,自动检测缺失和未使用的依赖,防止发布遗漏
- 构建产物自动检查导出路径是否与
package.json一致 - Source Map 在生产环境建议关闭或隐藏,避免泄露源码
- 注意
externals配置,确保运行时依赖不被意外排除
已知性能瓶颈
- 冷启动构建速度比 tsup(纯 esbuild)慢约 2-3 倍,因 Rollup 捆绑过程更重
- 类型声明生成(特别是大型项目)可能成为瓶颈
- Watch 模式的重新构建速度不如 esbuild-only 方案
技术对比
与同类工具对比
| 特性 | unbuild | tsup | pkgroll | tsdown |
|---|---|---|---|---|
| 底层引擎 | Rollup + esbuild | esbuild | Rollup + esbuild | Rolldown(Rust) |
| 周下载量 | ~320K | ~6.2M | ~90K | 新兴增长中 |
| 配置方式 | build.config.ts / package.json 自动推断 | tsup.config.ts | 零配置(读取 package.json exports) | tsdown.config.ts |
| Stub/代理模式 | ✅(jiti,核心优势) | ❌ | ❌ | ❌ |
| Bundleless(mkdist) | ✅ | ❌ | ❌ | ❌ |
| CJS + ESM 双输出 | ✅ | ✅ | ✅ | ✅ |
| 类型声明生成 | ✅(.d.ts/.d.mts/.d.cts) | ✅ | ✅ | ✅ |
| 构建速度 | 中等(冷启动 ~3.4s) | 极快(~1.2s) | 中等(~2.1s) | 极快(Rust) |
| Watch 更新 | ~280ms | ~120ms | ~190ms | 极快 |
| Rollup 插件兼容 | ✅ | ❌ | ✅ | ✅(Rolldown 兼容层) |
| 生态集成 | Nuxt/UnJS 深度集成 | 通用 | 通用 | Rolldown/Vite 生态 |
| Monorepo 友好度 | ⭐⭐⭐(最佳) | ⭐⭐ | ⭐⭐ | ⭐⭐ |
选择建议
- 选 unbuild:Monorepo 开发、Nuxt/UnJS 生态项目、需要 Rollup 插件生态、需要 Bundleless 模式
- 选 tsup:追求极致构建速度、通用 TypeScript 库、最大社区支持
- 选 pkgroll:零配置、简单库、已有清晰的
package.jsonexports - 选 tsdown:追求 Rolldown 性能红利、面向未来的 Rust 工具链
最佳实践
1. 双格式输出
// build.config.ts
export default defineBuildConfig({
rollup: {
emitCJS: true, // 同时输出 ESM 和 CJS
},
declaration: 'compatible', // 生成完整类型声明
})确保 package.json 的 exports 条件导出完整覆盖 import/require/types。
2. Monorepo 使用 Stub 模式
# 所有包运行 stub
pnpm -r exec unbuild --stub消费方应用直接引用源码,修改即时生效,无需监听和重建。
3. 组件库使用 mkdist
export default defineBuildConfig({
entries: [
{ builder: 'mkdist', input: 'src/components/' },
],
declaration: true,
})保持组件独立文件结构,支持按需引入和 tree-shaking。
4. 合理配置 externals
export default defineBuildConfig({
// 对等依赖和大型框架应声明为 external
externals: ['vue', 'react', 'lodash'],
})避免将 peerDependencies 或大型依赖打包进产物。
5. 使用 hooks 扩展构建流程
export default defineBuildConfig({
hooks: {
'build:done': async (ctx) => {
// 构建完成后自动复制额外文件
await fs.copyFile('README.md', 'dist/README.md')
},
},
})常见陷阱
- 忘记配置
emitCJS: true:默认只输出 ESM,如需 CJS 必须显式开启 - declaration 配置冲突:
declaration: undefined时自动检测可能不符合预期,建议显式设置 - Stub 模式残留:发布前确保运行
unbuild(不带--stub)进行真正的生产构建 - externals 遗漏:未在 externals 中声明的依赖会被打包进产物,可能导致体积膨胀或运行错误
- mkdist 不支持 tree-shaking:bundleless 模式的产物不支持跨文件 tree-shaking,需按需引入
技术局限与边界
已知限制
- 构建速度:生产构建基于 Rollup,冷启动速度不如纯 esbuild 方案(tsup 快 2-3 倍)
- 应用构建不适用:unbuild 专为库/包设计,不适合构建 Web 应用(应使用 Vite/Next.js 等)
- CSS/样式处理有限:不像 Vite 那样内置完整的 CSS 处理能力,需额外插件
- Web Worker / WASM:不支持或支持有限,需要额外配置
- 浏览器目标优化:主要面向 Node.js 库和同构库,浏览器专属优化不如 Vite
- 插件兼容性:虽然底层是 Rollup,但并非所有 Rollup 插件都经过测试
- 社区规模:相比 tsup(6.2M 周下载量),unbuild 社区较小(320K),遇到问题时可参考的资源较少
不适用场景
- Web 应用构建(选择 Vite / Next.js / Nuxt)
- 需要极致构建速度的大型项目(考虑 tsup 或 tsdown)
- 复杂的 CSS/样式处理管线(考虑 Vite)
- 纯前端浏览器库且需要完整资源处理(考虑 Vite library mode)
迁移注意事项
- 从 tsup 迁移:配置风格不同,需将
tsup.config.ts转换为build.config.ts;注意 rollup 选项与 esbuild 选项的差异 - 从 tsc 迁移:unbuild 提供更丰富的产物格式和打包能力,但需调整项目结构适配入口约定
- 向 obuild 迁移:UnJS 团队正在实验基于 Rolldown 的 obuild,未来可能成为 unbuild 的替代方案;目前仍处于实验阶段,不建议生产使用
学习资源
官方资源
- unbuild GitHub 仓库 — 源码和 README
- UnJS 官方包页面 — 包信息和链接
- unbuild releases — 版本更新日志
- unbuild issues — 问题追踪和讨论
教程与文章
- 可能是最全的 unbuild 使用文档(知乎) — 中文详细教程
- 还在用 rollup 打包库?试试 unbuild 吧(掘金) — 中文入门指南
- 使用 unbuild 搭建 JavaScript 构建系统笔记(阿里云开发者社区) — 工程化实践
- unbuild 的基本使用(掘金) — 基础用法
- unbuild 使用文档(掘金) — 综合文档
- tsup vs unbuild vs pkgroll (2026) — PkgPulse — 英文对比指南
- Best TypeScript-First Build Tools 2026 — PkgPulse — 英文综合评测
社区资源
- UnJS Discord — UnJS 官方 Discord 频道
- Nuxt Discord — Nuxt 社区(unbuild 相关讨论)
- GitHub Discussions — GitHub 讨论区
- UnJS Twitter/X — 官方动态
- Reddit r/Nuxt — Nuxt 社区讨论
2026 年现状
最新版本
- 当前稳定版:v3.6.1(2025 年 8 月 15 日)
- 2025 年版本节奏:v3.4.2 → v3.5.0 → v3.6.0 → v3.6.1,保持活跃的迭代
社区活跃度
- GitHub 星数:2700+
- npm 月下载量:320K+
- 代码贡献者:持续增长
- UnJS 整体生态月下载量:4.21 亿次
发展趋势
- obuild(Rolldown 继任者):UnJS 团队正在实验基于 Rolldown(Rust 实现的 Rollup 兼容打包器)的下一代构建工具
obuild。随着 Vite 8 已采用 Rolldown 替代 esbuild + Rollup,Rolldown 生态日趋成熟,obuild 有望在未来继承 unbuild 的定位并大幅提升构建速度 - Rolldown 生态成熟:Rolldown 1.0 RC 已于 2026 年 1 月发布,Rust 构建工具链正在成为主流
- tsdown 竞争:基于 Rolldown 的 tsdown 作为新兴竞争者快速增长,unbuild 需要跟进 Rust 化趋势
- Nuxt 4 生态:Nuxt 4 持续使用 UnJS 工具链,unbuild 作为基础设施地位稳固
- Monorepo 场景优势持续:Stub 模式仍是 unbuild 相比 tsup 等工具的独特差异化优势
未来路线图
- obuild 从实验阶段走向生产可用
- 可能引入 Rolldown 作为底层引擎替代 Rollup + esbuild
- 持续优化 TypeScript 声明生成性能
- 加强与 UnJS 生态其他包的协同(如 unplugin 统一插件系统)