unbuild logo

unbuild

UnJS 生态的统一 JavaScript/TypeScript 库构建系统,基于 Rollup + esbuild,零配置打包,Monorepo 友好。

打包工具RollupesbuildUnJS

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.jsonexports 字段推断构建入口和输出格式,绝大多数场景下无需编写额外配置文件。同时它独创了 Stub(插桩)模式——利用 jiti 生成轻量代理文件,将 dist 产物直接映射到源码,使 Monorepo 中的包在开发阶段无需重复构建即可热更新,被社区称为"Monorepo 杀手级特性"。

自 2021 年发布以来,unbuild 经历了从 v1 到 v3 的持续迭代,截至 2026 年 7 月最新稳定版为 v3.6.1。UnJS 团队还在实验基于 Rolldown(Rust 实现)的下一代继任者 obuild,以追求更快的构建速度。unbuild 在 npm 上月下载量超过 32 万次,GitHub 超过 2700 星,是 TypeScript 库构建工具领域的重要选择之一。

基本信息

快速上手

安装

# 使用 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.jsonexportsmaintypes 字段推断入口和输出格式。

方式二: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       │
└──────────────────────────────────────────────────┘

核心工作流程

  1. 配置解析:读取 build.config.ts 或从 package.json 自动推断
  2. 入口发现:通过 entries 配置或 autoPreset 扫描 src/ 目录
  3. 构建执行:根据每个 entry 指定的 builder 分别执行(rollup 或 mkdist)
  4. 类型生成:通过 rollup-plugin-dts 或 mkdist 生成 .d.ts 声明文件
  5. 产物输出:写入 outDir(默认 dist/),输出大小和导出信息摘要

核心特性

  • Rollup 驱动的生产级打包:基于 Rollup 的 tree-shaking 和代码分割能力,生成高质量的 ESM/CJS 产物,内置大量优质 Rollup 插件
  • esbuild 高速转译:使用 esbuild 处理 TypeScript/ESNext 转译,比传统 rollup-plugin-typescript2 快数十倍
  • 零配置自动推断:自动从 package.jsonexports/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:preparebuild: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 类型声明捆绑
mkdistBundleless 文件到文件转译
jiti运行时 TS/ESM 执行,Stub 模式核心
untyped从配置生成 TypeScript 类型定义
defu递归对象合并,用于配置解析
hookable构建生命周期钩子管理
magic-stringSource 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/ 现在指向源码,修改即时生效

发布检查清单

  1. 运行 unbuild 后检查 CLI 输出的包大小和导出信息
  2. 确认 dist/ 目录中包含 .mjs.cjs.d.ts 等所有预期产物
  3. 注意 unbuild 会自动检查缺失或未使用的依赖,CI 中会报错
  4. 使用 files 字段限制发布文件,推荐 ["dist"]

性能与安全

性能特点

指标数据
冷启动构建(50 文件)~3.4 秒
Watch 模式更新~280ms
Stub 插桩模式~50ms
  • 生产构建使用 Rollup 保证产物质量和 tree-shaking,速度略慢于纯 esbuild 方案(如 tsup)
  • Stub 模式极快(50ms),因为仅生成代理文件不做实际捆绑
  • esbuild 处理转译,比传统 Rollup + TypeScript 插件方案快 10-30 倍

优化建议

  • 启用 minifyrollup.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 方案

技术对比

与同类工具对比

特性unbuildtsuppkgrolltsdown
底层引擎Rollup + esbuildesbuildRollup + esbuildRolldown(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.json exports
  • 选 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 的替代方案;目前仍处于实验阶段,不建议生产使用

学习资源

官方资源

教程与文章

社区资源

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 亿次

发展趋势

  1. obuild(Rolldown 继任者):UnJS 团队正在实验基于 Rolldown(Rust 实现的 Rollup 兼容打包器)的下一代构建工具 obuild。随着 Vite 8 已采用 Rolldown 替代 esbuild + Rollup,Rolldown 生态日趋成熟,obuild 有望在未来继承 unbuild 的定位并大幅提升构建速度
  2. Rolldown 生态成熟:Rolldown 1.0 RC 已于 2026 年 1 月发布,Rust 构建工具链正在成为主流
  3. tsdown 竞争:基于 Rolldown 的 tsdown 作为新兴竞争者快速增长,unbuild 需要跟进 Rust 化趋势
  4. Nuxt 4 生态:Nuxt 4 持续使用 UnJS 工具链,unbuild 作为基础设施地位稳固
  5. Monorepo 场景优势持续:Stub 模式仍是 unbuild 相比 tsup 等工具的独特差异化优势

未来路线图

  • obuild 从实验阶段走向生产可用
  • 可能引入 Rolldown 作为底层引擎替代 Rollup + esbuild
  • 持续优化 TypeScript 声明生成性能
  • 加强与 UnJS 生态其他包的协同(如 unplugin 统一插件系统)