
# 构建

> 打包器选择和构建输出调优。

::note
本页所有示例都假设已在 `nitro.config.ts` 中导入以下内容：

```ts
import { defineConfig } from "nitro";
```
::

### `builder`

- 类型：`"rollup"`{lang=ts} | `"rolldown"`{lang=ts} | `"rspack"`{lang=ts} | `"vite"`{lang=ts} | `"bun"`{lang=ts} | `false`{lang=ts}
- 默认值：`undefined`{lang=ts}（自动检测）

指定用于构建的打包器。

```ts
export default defineConfig({
  builder: "vite",
});
```

未设置时，如果你的 `vite.config` 使用了 `nitro()` 插件，Nitro 会使用 `vite`，否则使用 `rolldown`。构建器包会从项目中解析（`rolldown` 也可以通过 `vite` 解析），并在构建时按需安装（CI 除外，参见 [`deps.install`](#deps)）。开发模式下，如果未安装 `rolldown` 且未设置 [`rollupConfig`](#rollupconfig) 或 [`rolldownConfig`](#rolldownconfig)，`nitro dev` 会在不使用构建器的情况下运行（`builder: false`），而 `nitro build` 会提示安装构建器。Nitro 在 Bun 上运行时（例如 `bun --bun nitro build`），如果项目中既未安装 `rolldown` 也未安装 `vite`，则会改用实验性的 `bun` 构建器，包括开发模式。

将 `builder` 设为 `false`（实验性功能）可在不打包的情况下运行服务器源文件。此时 `nitro dev` 会在 [env-runner](https://github.com/unjs/env-runner) worker 中直接运行文件，Nitro 虚拟模块由内存提供，并在每次文件变更时启动新的 worker。[`nitro start`](/docs/cli#nitro-serve)（或 `nitro serve`）也会以生产模式直接运行源文件，不执行构建步骤，与配置的构建器无关。`nitro preview` 只提供构建产物。[预渲染](/docs/prerendering)也会以相同方式运行源文件；未安装 `rolldown` 时，`vite` 构建器也会使用此方式。目前尚不支持 `nitro build`。

模块会像打包构建中一样按需转换：包括 TypeScript 和 JSX、`import.meta.*` 和 [`replace`](#replace) 值、[`alias`](#alias)、无扩展名导入、`raw:`/`text`/`bytes` 导入以及 WebAssembly。

::note
- 在 Bun 上，尚不能解析不带文件扩展名的别名（例如 `~/utils`）和 WebAssembly 导入。
- 项目、其扫描目录和 Nitro 以外的文件（例如链接的工作区包）会按原样加载，不执行上述转换。
- 打包器选项（`rollupConfig`、`rolldownConfig`）以及模块通过 `build:config` 钩子添加的插件均不适用。插件请使用 [`buildPlugins`](#buildplugins)。
::

将 `builder` 设为 `"rspack"`（实验性功能），可使用 [Rspack](https://rspack.rs)（`@rspack/core` v2.3 及更高版本，按需安装）打包服务器。Nitro 自带的构建插件和 [`buildPlugins`](#buildplugins) 会在 Rspack 中运行，TypeScript 和 JSX 则由其内置的 SWC 加载器编译。其他选项请使用 [`rspackConfig`](#rspackconfig)。

::note
使用 `rspack` 时，会应用 [`rollupConfig`](#rollupconfig) 和 [`rolldownConfig`](#rolldownconfig)（由预设使用）中的这些选项：`plugins`、`external`（在解析导入前调用）、`output.entryFileNames` 和 `output.chunkFileNames`（包含 `[name]` 和 `[hash]` 的字符串）、`output.banner`、`output.footer`、`output.intro` 和 `output.outro`（字符串或同步函数）、`output.inlineDynamicImports: true`、`output.sourcemapExcludeSources` 以及 `output.sourcemapPathTransform`。其他选项会被忽略，Nitro 会对此发出警告。
::

将 `builder` 设为 `"bun"`（实验性功能），可使用 [Bun 打包器](https://bun.com/docs/bundler)（`Bun.build`）打包服务器。必须在 Bun 上运行 Nitro（例如 `bun --bun nitro build`），否则 Nitro 会抛出错误。该构建器支持所有预设，而不仅限于 `bun`，并支持 `nitro dev`。

::note
- Nitro 构建插件、[`buildPlugins`](#buildplugins) 以及 [`rollupConfig`](#rollupconfig) 和 [`rolldownConfig`](#rolldownconfig) 中的插件会在同一个 Bun 插件中运行。支持 `buildStart`、`resolveId`、`load`、`transform`、`buildEnd`、`renderChunk`、`resolveFileUrl`、`generateBundle` 和 `writeBundle` 钩子。JavaScript 和 TypeScript 以外的文件只有在 `load` 钩子加载它们，或钩子的 `filter` 通过 `id` 指定它们时，才会传给 `transform` 钩子。Bun 不提供输入 source map，因此 `transform` 和 `renderChunk` 钩子不会更新 source map。
- `rollupConfig` 和 `rolldownConfig` 中只有 `plugins`、`external`、`platform: "node"` 以及 `output` 的 `entryFileNames`、`chunkFileNames`、`format`、`inlineDynamicImports`、`banner` 和 `footer`（字符串形式）会生效。其他选项请使用 [`bunConfig`](#bunconfig)。
- 分块由 Bun 命名（`_chunks/[name]-[hash].mjs`），库分块不会归组。
- Bun 没有 `neutral` 目标：不兼容 Node.js 的预设会使用 `browser` 目标，该目标会优先解析包的 `browser` 导出条件和 `browser` 字段。
- 打包后的 CommonJS 模块会将 `__dirname` 和 `__filename` 设为构建机器上的绝对路径。
::

### `buildPlugins`

- 类型：`NitroBuildPluginOption[]`{lang=ts}
- 默认值：`[]`{lang=ts}

应用于所有[构建器](#builder)（`rollup`、`rolldown`、`rspack`、`vite`、`bun` 和 `false`）的构建插件。会解析嵌套数组和 Promise，并跳过假值条目。

插件使用 Rollup 插件接口。建议为 `resolveId`、`load` 和 `transform` 钩子设置 `filter`：这些钩子受所有构建器支持。

`enforce: "pre"` 插件会排在 Nitro 自身插件之前，其他插件排在其后（`enforce: "post"` 最后）。钩子自身的 `order` 优先级更高：Nitro 的一些钩子（例如虚拟模块解析）会使用 `order: "pre"`，需要在它们之前运行的钩子也应设置该值。

::note
- 不同构建器在插件运行前后的处理有所不同。使用 `rolldown` 和 `bun` 时，`transform` 钩子接收尚未转换的 TypeScript 和 JSX（插件运行后才会编译）；使用 `rollup` 时，仅 `enforce: "pre"` 插件会收到未转换的内容。使用 `vite` 时，Vite 会先执行自己的解析和转换。
- 使用 `vite` 时，插件仅作为打包器插件应用于 `nitro` 环境；不支持 Vite 专属选项和钩子（例如 `apply` 或 `configureServer`）。Vite 插件请添加到 Vite 的 `plugins` 中。
- 使用 `rspack` 时，插件会在 Rspack 内运行。Rspack 支持 `resolveId`、`load` 和 `transform`（接收尚未转换的 TypeScript 和 JSX）、`buildStart`、`buildEnd`、`renderChunk`、`generateBundle`、`writeBundle` 和 `closeBundle`，并会对其他钩子发出警告。插件上下文功能有限：`this.emitFile` 只能输出资源（带有 `source`）；`this.load` 解析为 `{ id, code }`；`this.getModuleInfo` 只包含模块导入方和导入项的 id；`buildStart` 不接收输入选项；输出分块不包含导入、导出或 source map（`map`）信息。开发模式下，每次重新构建都会运行 `buildStart` 和 `closeBundle`。`load` 和 `transform` 仅处理 JavaScript、TypeScript 模块及虚拟模块。
- `builder: false` 时，插件会在 [env-runner](https://github.com/unjs/env-runner) 中运行。它只支持 `resolveId`、`load` 和 `transform`（插件上下文功能有限），并会对其他钩子发出警告。钩子只会接收 JavaScript 和 TypeScript 模块，除非其 `filter` 通过 `id` 或 `moduleType` 指定了其他文件；只有 `filter` 指定 `node_modules` 时，才会接收其中的文件。
::

```ts
export default defineConfig({
  buildPlugins: [
    {
      name: "my-virtual-module",
      resolveId: {
        filter: { id: /^virtual:my-module$/ },
        handler: (id) => `\0${id}`,
      },
      load: {
        filter: { id: /^\0virtual:my-module$/ },
        handler: () => `export default "Hello!"`,
      },
    },
  ],
});
```

Nitro 模块可以通过 `nitro.options.buildPlugins.push(plugin)` 添加插件。

### `rollupConfig`

额外的 Rollup 配置。

```ts
export default defineConfig({
  rollupConfig: {
    output: { manualChunks: { vendor: ["lodash-es"] } },
  },
});
```

### `rolldownConfig`

额外的 Rolldown 配置。

```ts
export default defineConfig({
  rolldownConfig: {
    output: { banner: "/* built with nitro */" },
  },
});
```

### `rspackConfig`

额外的 Rspack 配置（适用于实验性的 `rspack` 构建器），会与 Nitro 生成的配置合并。

```ts
export default defineConfig({
  builder: "rspack",
  rspackConfig: {
    optimization: { concatenateModules: false },
  },
});
```

### `bunConfig`

`bun`[构建器](#builder)的额外 [`Bun.build`](https://bun.com/docs/bundler) 选项。

```ts
export default defineConfig({
  builder: "bun",
  bunConfig: {
    naming: { chunk: "chunks/[name]-[hash].mjs" },
  },
});
```

### `vite`

`vite` 构建器和 `nitro/vite` 插件的选项。

- `path`：要使用的 `vite` 包，可以是指向其目录或入口的路径或 `file://` URL（与 [`deps.paths.vite`](#deps) 相同）。默认情况下，`nitro/vite` 插件会使用当前运行的 `vite`，`vite` 构建器则从项目根目录解析它。
- `assetsImport`：启用 `?assets` 导入，以收集入口中的 CSS 和 JS 资源（默认值：`true`）。
- `serverReload`：仅服务器模块发生变化时重新加载开发服务器（以及浏览器，默认值：`true`）。

```ts
export default defineConfig({
  vite: {
    path: import.meta.resolve("vite"),
  },
});
```

### `services`

- 类型：`Record<string, { entry: string }>`{lang=ts}
- 默认值：`{}`{lang=ts}

导出 `fetch` 处理器的服务器入口。它们由 [`nitro/vite`](/docs/vite) 或 [`nitro/rsbuild`](/docs/rsbuild) 插件在各自的环境中构建，并通过 `nitro/services` 中的 `fetchService(name, input, init?)` 调用。

项目目录或服务器目录中的 `app/`、`src/` 或根目录如果存在 `entry-server` 文件，Nitro 会据此检测 `ssr` 服务；带有入口的服务器环境也会自动注册。未设置渲染器时，未匹配的路由会由 `ssr` 服务渲染。

```ts
export default defineConfig({
  services: { api: { entry: "./src/api-entry.ts" } },
});
```

### `deps`

Nitro 按需安装的可选依赖项（例如 `vite`、`rolldown`、`rollup`、`unstorage`、`db0` 或 `unenv`）的选项。

- `paths`：按包名显式指定要使用的包。每个值可以是指向包目录或入口的路径或 `file://` URL。相对路径以 [`rootDir`](/config/directories#rootdir) 为基准解析。
- `install`：是否允许安装缺失的包（默认值：`true`，CI 中为 `false`）。禁用后，构建会失败并提示添加缺失包的命令，因此只会使用已提交到项目中的依赖。在 CI 中也要按需安装时，请设为 `true`。加载配置文件本身所需的包（`jiti`、`giget`，以及不支持原生加载的运行时所需的 `dotenv`）只会在 CI 以外安装，与此选项无关。

默认情况下，这些包会从项目中解析，缺失时按需安装（CI 除外）。基于 Nitro 构建的框架可以在 `deps.paths` 中传入自己的包副本，以确保运行所依赖的版本。服务器包也会使用其中的 `unstorage`、`db0` 和 `unenv`。显式指定的包不会被安装；版本超出支持范围时，Nitro 会发出警告。如果 [`rootDir`](/config/directories#rootdir) 位于 `node_modules` 中（例如框架使用自己的包目录），也不会安装任何包：框架必须在自身依赖中声明所用包，或通过 `deps.paths` 传入这些包。

```ts
export default defineConfig({
  deps: {
    paths: {
      unstorage: import.meta.resolve("unstorage"),
      db0: import.meta.resolve("db0"),
    },
  },
});
```

若要完全禁止安装这些包（包括本地环境），请禁用 `install`：

```ts
export default defineConfig({
  deps: { install: false },
});
```

`deps.paths.vite` 是 [`vite.path`](#vite) 的别名。

### `entry`

打包器入口。

```ts
export default defineConfig({
  entry: "./server/entry.ts", // custom entry file
});
```

### `alias`

模块解析的路径别名。

```ts
export default defineConfig({
  alias: {
    "~utils": "./src/utils",
    "#shared": "./shared",
  },
});
```

使用 Vite 构建器时，这些别名会应用于每个 Vite 环境。如果 Vite 的 `resolve.alias`（来自 Vite 配置或其他插件，且 `find` 为字符串）将同一个键映射到其他目标，Nitro 目标只应用于 `nitro` 环境，其他环境（例如 `client` 和 `ssr`）则使用 Vite 目标。

### `inject`

在包中引用全局变量时，将其替换为对应导入。值可以是模块 id（默认导出），也可以是 `[id, exportName]` 元组。

将全局变量设为 `false` 可移除默认注入（例如为 [`node: false`](#node) 构建添加的注入）。

```ts
export default defineConfig({
  inject: {
    Buffer: ["node:buffer", "Buffer"],
    performance: false,
  },
});
```

### `polyfills`

在服务器入口之前为执行副作用而导入的模块。在条目前加上 `!` 可移除默认 polyfill。

[`node: false`](#node) 构建默认会添加 `#nitro/runtime/polyfills/global`、`#nitro/runtime/polyfills/process`、`#nitro/runtime/polyfills/buffer` 和 `#nitro/runtime/polyfills/timers`（例如 `"!#nitro/runtime/polyfills/timers"` 会移除 `setImmediate` polyfill）。

```ts
export default defineConfig({
  polyfills: ["./polyfills/intl.ts"],
});
```

### `builtinModules`

由目标运行时提供的模块，例如 `cloudflare:workers` 或 Deno 上的 `node:fs`。这些 id 的导入会在输出中保持原样。

内置模块不会被打包、追踪或复制到输出中，因此这里只应列出运行时本身提供的模块。若要让 npm 包不进入构建包，请改用 [`traceDeps`](#tracedeps)。[`node`](#node) 为 `true` 时，Node.js 内置模块会自动处理。

在条目前加上 `!` 可移除默认项（例如由预设添加的项目）。

```ts
export default defineConfig({
  builtinModules: ["cloudflare:workers"],
});
```

::note
预设也会添加默认的 `alias`、`inject`、`polyfills` 和 `builtinModules` 条目（例如，Cloudflare 和 Deno 会映射其原生支持的 Node.js 内置模块）。这些选项中你自行设置的值始终优先。

`unenv` 选项已弃用。通过它传入的预设仍会生效，顺序在预设默认值之后、你自己的选项之前。
::

### `minify`

- 默认值：`false`{lang=ts}

压缩构建包。

部分预设（尤其是 Worker 运行时）默认启用压缩。调试生产、Worker 或边缘构建时，请设置 `minify: false`，以便堆栈跟踪保持可读。

```ts
export default defineConfig({
  minify: true, // minify production bundle
});
```

```ts
export default defineConfig({
  minify: false, // easier to debug workers / edge bundles
});
```

### `inlineDynamicImports`

- 默认值：`false`{lang=ts}

将所有代码打包到单个文件中，而不是为每个路由创建单独的分块。

设为 `false` 时，每个路由处理器会成为单独的分块并按需加载；设为 `true` 时，所有内容会打包在一起。部分预设默认启用此选项。

```ts
export default defineConfig({
  inlineDynamicImports: true, // single output file
});
```

### `sourcemap`

- 默认值：`false`{lang=ts}

启用 source map 生成。参见[选项说明](https://rollupjs.org/configuration-options/#output-sourcemap)。

```ts
export default defineConfig({
  sourcemap: true, // generate .map files
});
```

### `node`

- 默认值：`true`{lang=ts}

指定构建是否用于 Node.js。设为 `false` 时，Nitro 会添加默认的 [`alias`](#alias)、[`inject`](#inject) 和 [`polyfills`](#polyfills) 条目，以 polyfill Node.js 全局变量和内置模块（使用 [unenv](https://github.com/unjs/unenv)），并相应调整自身行为。

目标运行时未提供的 Node.js 内置模块（例如 Cloudflare 上的 `node:inspector`）会使用 [unenv](https://github.com/unjs/unenv) 进行 polyfill。只有构建导入了此类模块时，才会从项目中解析 `unenv`，并在需要时按需安装（CI 除外，参见 [`deps.install`](#deps)）。

```ts
export default defineConfig({
  node: false, // target non-Node.js runtimes
});
```

### `replace`

构建时字符串替换。

```ts
export default defineConfig({
  replace: {
    "process.env.APP_VERSION": JSON.stringify("1.0.0"),
  },
});
```

### `commonJS`

指定 Rollup CommonJS 插件的其他配置。

```ts
export default defineConfig({
  commonJS: {
    requireReturnsDefault: "auto",
  },
});
```

### `exportConditions`

模块解析的自定义导出条件。

```ts
export default defineConfig({
  exportConditions: ["worker", "production"],
});
```

### `noExternals`

- 默认值：`false`{lang=ts}

阻止将包标记为外部依赖。外部依赖会在运行时导入，而不是打包进产物，因此无法使用你的 `alias` 配置。

生产构建中，Nitro 已经会打包几乎所有内容：只有原生包、其他无法打包的包，以及列在 [`traceDeps`](#tracedeps) 中的包会保留为外部依赖。开发模式下，为了提高速度，`node_modules` 中的依赖会保持为外部依赖，此时该选项最有用。

设为 `true` 可打包所有内容，包括通常会保留为外部依赖的包：

```ts
export default defineConfig({
  noExternals: true, // bundle all dependencies
});
```

#### 内联特定包 {#inlining-specific-packages}

传入数组可仅内联部分模块。`RegExp` 条目按原样使用；字符串条目会经过转义，并作为路径子字符串进行匹配。

每个模式都会与导入说明符（例如 `@scope/my-lib`）以及解析后的绝对文件路径（例如 `/…/node_modules/@scope/my-lib/dist/index.mjs`）进行匹配。任意一项匹配时，模块都会保留在构建包中，因此通常只需填写包名：

```ts
export default defineConfig({
  alias: {
    "@shared": "./shared",
  },
  noExternals: ["@scope/my-lib"],
});
```

需要更精确的匹配时，请使用路径模式。例如，在 monorepo 中内联一个包而不匹配名称相似的包：

```ts
export default defineConfig({
  noExternals: [/packages[\\/]my-lib/],
});
```

此类模式中请使用 `[\\/]` 代替 `/`，以便同时匹配 Windows 路径。

::note
在 Nitro 2 中，此选项名为 `externals.inline`。
::

### `traceDeps`

- 默认值：`[]`{lang=ts}

要追踪并包含在构建输出中的额外依赖项。

支持以下特殊前缀：
- `!pkg`：从追踪中排除内置包。
- `pkg*`：完整追踪，复制包中的所有文件，而不只是已追踪的文件。

```ts
export default defineConfig({
  traceDeps: [
    "sharp",
    "better-sqlite3",
    "my-pkg*", // full trace (copy all package files)
    "!unwanted-pkg", // exclude from tracing
  ],
});
```

### `traceOpts`

传递给 [nf3](https://github.com/unjs/nf3) 以进行依赖追踪的高级选项。

```ts
export default defineConfig({
  traceOpts: {
    // Options passed to @vercel/nft for file tracing
    nft: { /* ... */ },
    // Alias for module paths when tracing
    traceAlias: { "old-pkg": "new-pkg" },
    // Preserve or set file permissions when copying (true or octal like 0o755)
    chmod: true,
    // Transform traced files before copying
    transform: [
      { filter: (id) => id.endsWith(".js"), handler: (code) => code },
    ],
    // Hook into tracing lifecycle
    hooks: {
      tracedPackages(pkgs) {
        console.log("Traced packages:", Object.keys(pkgs));
      },
    },
  },
});
```

### `oxc`

`rollup` 构建器的 OXC 选项，包括 `minify` 和 `transform` 子选项。

`minify` 使用 `rolldown` 的压缩器。如果未安装 `rolldown`，则会发出警告并跳过压缩。

```ts
export default defineConfig({
  oxc: {
    minify: { compress: true, mangle: true },
  },
});
```
