website/docs/en/guide/tech/nestjs.mdx
import { PackageManagerTabs } from '@theme';
Rspack can build NestJS applications. Compared with tsc, Rspack can bundle application code, transform TypeScript with SWC, enable development HMR, and leave runtime dependencies external when needed.
Start with the common Node.js application configuration, then add the NestJS settings described below. You can also use the NestJS example in rstack-examples as a reference. It includes a complete rspack.config.mjs, development script, production build script, and HMR entry.
The rstack-examples repository contains a complete NestJS application built with Rspack.
Install the common Node.js build dependencies from the Node.js guide, then install the NestJS runtime packages:
<PackageManagerTabs command="add @nestjs/common @nestjs/core @nestjs/platform-express reflect-metadata rxjs" />NestJS applications run in Node.js, so most configurations can follow the common Node.js configuration. The main NestJS-specific requirement is decorator metadata, which NestJS uses at runtime.
The following configuration is adapted from the NestJS example. It combines the common Node.js setup with the decorator metadata options required by NestJS:
// @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/],
}),
],
});
Use rspack dev during development and rspack build for production:
{
"scripts": {
"build": "rspack build",
"dev": "rspack dev",
"start": "node dist/main.js"
}
}
dev: Runs Rspack Dev Server, writes the server bundle to disk, and starts dist/main.js.build: Creates a production bundle without the HMR polling entry.start: Runs the production bundle with Node.js.NestJS uses decorators such as @Module(), @Controller(), @Injectable(), and @Get(). Configure builtin:swc-loader so SWC can parse these decorators and emit the metadata NestJS needs:
export default {
module: {
rules: [
{
test: /\.ts$/,
use: {
loader: 'builtin:swc-loader',
options: {
detectSyntax: 'auto',
jsc: {
parser: {
decorators: true,
},
transform: {
legacyDecorator: true,
decoratorMetadata: true,
},
},
},
},
},
],
},
};
If your project also runs tsc, keep experimentalDecorators and emitDecoratorMetadata enabled in tsconfig.json so TypeScript and Rspack use the same decorator assumptions:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
Add @rspack/core/hot/poll only in development. If it is included in the production bundle, the Node.js application will fail at runtime because HMR is not available in build mode:
export default {
entry: {
main:
process.env.NODE_ENV === 'production'
? './src/main.ts'
: ['@rspack/core/hot/poll?100', './src/main.ts'],
},
};
Add HMR handling to the NestJS bootstrap file. This closes the old application instance before accepting the updated module:
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();
See Node.js - Configure development HMR for the shared Rspack entry, writeToDisk, RunScriptWebpackPlugin, and externals allowlist settings used with this bootstrap code. If your project needs ESM output, see Node.js - Use ESM output.
When minifying a NestJS server bundle, keep class names and function names. NestJS can rely on stable class and handler references through metadata reflection and execution context APIs.
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,
},
},
}),
],
},
};
If a NestJS dependency includes a Node.js native addon (.node module), follow Node.js - Native node modules to emit the addon with asset/resource and let Node.js load it at runtime.