> For AI agents: the complete documentation index is available at https://rspack.rs/zh/llms.txt, the full documentation bundle is available at https://rspack.rs/zh/llms-full.txt.

# NestJS

Rspack 可以用于构建 [NestJS](https://nestjs.com/) 应用。相比直接使用 `tsc`，Rspack 可以打包应用代码、通过 SWC 转译 TypeScript、支持开发阶段 HMR，并在需要时将运行时依赖作为 external 处理。

## 如何使用

请先参考通用的 [Node.js 应用配置](https://rspack.rs/zh/guide/integrations/node.md)，再补充本文介绍的 NestJS 配置。你也可以参考 `rstack-examples` 中的 [NestJS example](https://github.com/rstackjs/rstack-examples/tree/main/rspack/nestjs)，其中包含完整的 `rspack.config.mjs`、开发脚本、生产构建脚本和 HMR 入口。

## 示例

[rstack-examples](https://github.com/rstackjs/rstack-examples/tree/main/rspack/nestjs) 仓库包含了使用 Rspack 构建 NestJS 应用的完整示例。

## 安装依赖

先按 [Node.js 指南](https://rspack.rs/zh/guide/integrations/node.md#%E5%AE%89%E8%A3%85%E4%BE%9D%E8%B5%96)安装通用的 Node.js 构建依赖，然后安装 NestJS 运行时依赖：


```sh [npm]
npm add @nestjs/common @nestjs/core @nestjs/platform-express reflect-metadata rxjs
```

```sh [yarn]
yarn add @nestjs/common @nestjs/core @nestjs/platform-express reflect-metadata rxjs
```

```sh [pnpm]
pnpm add @nestjs/common @nestjs/core @nestjs/platform-express reflect-metadata rxjs
```

```sh [bun]
bun add @nestjs/common @nestjs/core @nestjs/platform-express reflect-metadata rxjs
```

```sh [deno]
deno add npm:@nestjs/common npm:@nestjs/core npm:@nestjs/platform-express npm:reflect-metadata npm:rxjs
```

## 基本概念

NestJS 应用运行在 Node.js 中，因此大部分配置都与通用的 [Node.js 配置](https://rspack.rs/zh/guide/integrations/node.md) 一致。除此之外，NestJS 还需要 decorator metadata，框架会在运行时读取这些信息。

- **Decorator metadata**：启用 TypeScript decorators 和 decorator metadata，保证依赖注入、控制器、路由、守卫、拦截器等 NestJS 能力正常工作。
- **HMR cleanup**：开发阶段 HMR 更新服务端 bundle 时，需要在接受更新前关闭旧的 Nest 应用实例。
- **Production minification**：保留 class name 和 function name，因为 NestJS 可能会通过 metadata reflection 和 execution context API 使用对应的引用。

## 配置 Rspack

以下配置改编自 NestJS 示例，它组合了通用 Node.js 配置和 NestJS 所需的 decorator metadata 选项：

```js title="rspack.config.mjs"
// @ts-check
import { defineConfig } from '@rspack/cli';
import { rspack } from '@rspack/core';
import { RunScriptWebpackPlugin } from 'run-script-webpack-plugin';
import nodeExternals from 'webpack-node-externals';

export default defineConfig({
  context: import.meta.dirname,
  target: 'node',
  entry: {
    main:
      process.env.NODE_ENV === 'production'
        ? './src/main.ts'
        : ['@rspack/core/hot/poll?100', './src/main.ts'],
  },
  output: {
    clean: true,
  },
  resolve: {
    extensions: ['...', '.ts', '.tsx', '.jsx'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: {
          loader: 'builtin:swc-loader',
          options: {
            detectSyntax: 'auto',
            jsc: {
              parser: {
                decorators: true,
              },
              transform: {
                legacyDecorator: true,
                decoratorMetadata: true,
              },
            },
          },
        },
      },
    ],
  },
  optimization: {
    minimizer: [
      new rspack.SwcJsMinimizerRspackPlugin({
        minimizerOptions: {
          compress: {
            keep_classnames: true,
            keep_fnames: true,
          },
          mangle: {
            keep_classnames: true,
            keep_fnames: true,
          },
        },
      }),
    ],
  },
  plugins: [
    process.env.NODE_ENV !== 'production' &&
      new RunScriptWebpackPlugin({
        name: 'main.js',
        autoRestart: false,
      }),
  ],
  devServer: {
    devMiddleware: {
      writeToDisk: true,
    },
  },
  externals: [
    nodeExternals({
      allowlist: [/@rspack\/core\/hot\/poll/],
    }),
  ],
});
```

## 配置脚本

开发阶段使用 `rspack dev`，生产构建使用 `rspack build`：

```json title="package.json"
{
  "scripts": {
    "build": "rspack build",
    "dev": "rspack dev",
    "start": "node dist/main.js"
  }
}
```

- `dev`：运行 Rspack Dev Server，将服务端 bundle 写入磁盘，并启动 `dist/main.js`。
- `build`：创建不包含 HMR polling 入口的生产 bundle。
- `start`：使用 Node.js 运行生产 bundle。

## 配置 TypeScript decorators

NestJS 使用 `@Module()`、`@Controller()`、`@Injectable()`、`@Get()` 等 decorators。需要配置 `builtin:swc-loader`，让 SWC 能够解析这些 decorators，并生成 NestJS 需要的 metadata：

```js title="rspack.config.mjs"
export default {
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: {
          loader: 'builtin:swc-loader',
          options: {
            detectSyntax: 'auto',
            jsc: {
              parser: {
                decorators: true,
              },
              transform: {
                legacyDecorator: true,
                decoratorMetadata: true,
              },
            },
          },
        },
      },
    ],
  },
};
```

如果项目同时运行 `tsc`，请在 `tsconfig.json` 中启用 `experimentalDecorators` 和 `emitDecoratorMetadata`，让 TypeScript 和 Rspack 使用一致的 decorator 配置：

```json title="tsconfig.json"
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}
```

## 配置开发 HMR

只在开发入口中添加 `@rspack/core/hot/poll`。如果生产 bundle 中包含它，Node.js 应用会在运行时失败，因为 build mode 下不会启用 HMR：

```js title="rspack.config.mjs"
export default {
  entry: {
    main:
      process.env.NODE_ENV === 'production'
        ? './src/main.ts'
        : ['@rspack/core/hot/poll?100', './src/main.ts'],
  },
};
```

在 NestJS bootstrap 文件中添加 HMR 处理，在接受更新前关闭旧的应用实例：

```ts title="src/main.ts"
declare const module: any;

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
  if (module.hot) {
    module.hot.accept();
    module.hot.dispose(() => app.close());
  }
}

bootstrap();
```

通用的 Rspack entry、`writeToDisk`、`RunScriptWebpackPlugin` 和 externals allowlist 设置请参考 [Node.js - 配置开发 HMR](https://rspack.rs/zh/guide/integrations/node.md#%E9%85%8D%E7%BD%AE%E5%BC%80%E5%8F%91-hmr)。如果你的项目需要 ESM 输出，请参考 [Node.js - 使用 ESM 输出](https://rspack.rs/zh/guide/integrations/node.md#%E4%BD%BF%E7%94%A8-esm-%E8%BE%93%E5%87%BA)。

## 配置生产压缩

压缩 NestJS 服务端 bundle 时，需要保留 class name 和 function name。NestJS 可能会通过 metadata reflection 和 execution context API 使用对应的 class 与 handler 引用。

```js title="rspack.config.mjs"
import { rspack } from '@rspack/core';

export default {
  optimization: {
    minimizer: [
      new rspack.SwcJsMinimizerRspackPlugin({
        minimizerOptions: {
          compress: {
            keep_classnames: true,
            keep_fnames: true,
          },
          mangle: {
            keep_classnames: true,
            keep_fnames: true,
          },
        },
      }),
    ],
  },
};
```

## Native node modules

如果 NestJS 依赖中包含 Node.js native addon（`.node` 模块），请参考 [Node.js - Native node modules](https://rspack.rs/zh/guide/integrations/node.md#native-node-modules)，使用 `asset/resource` 输出 addon，并让 Node.js 在运行时加载。
