从Nestjs10迁移到Nestjs11

本文提供了从 NestJS 10 迁移到 NestJS 11 的完整指南。NestJS 11 引入了许多新功能,同时包含了一些 轻微的不兼容更改,但 大多数用户不会受到影响。你可以查看完整的变更列表以获取详细信息。

NestJS 11 迁移指南

升级依赖包

你可以手动更新依赖包,但官方推荐使用 npm-check-updates (ncu) 进行自动更新,以简化升级过程。

Express v5 迁移

Express v52024 年正式发布,并在 2025 年成为稳定版本。在 NestJS 11 中,Express v5 现在是默认集成的版本。

路由匹配规则变更

Express v5 调整了路径匹配算法,主要变更包括:

  1. 通配符 * 必须带名称
  • 旧语法(Express v4):/*
  • 新语法(Express v5):/*splat/{*splat}(splat 只是一个变量名,可以自定义)
  1. ?(可选参数)不再支持
  • 旧语法:/:file?.ext
  • 新语法:/:file{.:ext}
  1. 正则表达式字符不再支持
  2. 部分特殊字符需要转义(如 ()[]?+!)。
  3. 参数名必须是合法的 JavaScript 标识符,或使用 :"paramName" 进行引用。
1
2
3
4
5
6
7
8
9
10
11
// 旧方式(Express v4)
@Get('users/*')
findAll() {
return '此路由在 Express v5 可能无法正常工作';
}

// 新方式(Express v5)
@Get('users/*splat') // 需要给通配符命名
findAll() {
return '此路由在 Express v5 可正常工作';
}

注意

  • *splat 只是一个占位符名称,可以随意更改,如 *wildcard

  • 如果你希望匹配 根路径,需要使用 /{*splat} 语法:

中间件路径调整

在 Express v5 中,如果你有适用于所有路由的中间件,需要更新路径:

1
2
3
4
5
// 旧方式(Express v4)
forRoutes('*'); // Express v5 可能不兼容

// 新方式(Express v5)
forRoutes('{*splat}'); // 现在推荐的方式

Express v5 的查询参数解析变更

适用于 Express v5

  • 之前,Express 默认使用 qs 库解析查询参数,支持嵌套对象和数组。

  • 现在,默认使用 简单解析器不再支持嵌套对象和数组

例如,以下查询字符串:

1
2
?filter[where][name]=John&filter[where][age]=30
?item[]=1&item[]=2

在 Express v5 不会被正确解析

如何恢复原行为:

1
2
3
4
5
6
7
8
9
10
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.set('query parser', 'extended'); // 重新启用 qs 库解析方式
await app.listen(3000);
}
bootstrap();

Fastify v5 迁移

NestJS 11 现在默认支持 Fastify v5

  • 几乎无痛升级,大部分用户无需调整。

  • 路径匹配规则未变,通配符 * 仍然适用。

中间件注册调整

Fastify v5 不再支持 (.*) 语法匹配所有路径,需使用 命名通配符

1
2
3
4
5
// 旧方式(Fastify v4)
.forRoutes('(.*)');

// 新方式(Fastify v5)
.forRoutes('*splat');

splat 只是一个占位符名称,可自定义。

模块解析算法优化

变更点

  • NestJS 10 及之前:使用 哈希计算 来标识动态模块。

  • NestJS 11:改为 对象引用,提升性能,减少内存占用。

影响

  • 以前,重复导入相同的动态模块会 自动去重

  • 现在,如果你希望模块 共享相同实例,需要手动管理:

1
const myModule = DynamicModule.forRoot({});

生命周期钩子执行顺序调整

  • 之前,OnModuleDestroy、OnApplicationShutdown 等 按初始化顺序执行

  • 现在,执行顺序反转(与初始化顺序相反)。

示例:

1
2
// A 依赖 BB 依赖 C
A -> B -> C
  • 模块初始化顺序:C -> B -> A

  • 模块销毁顺序:A -> B -> C(反转)

影响

全局模块 被视为依赖所有模块,因此 最先初始化,最后销毁

CacheModule 迁移

NestJS 11 的 @nestjs/cache-manager:

  • 迁移至 Keyv,提供统一的 键值存储接口

  • Redis 配置方式变更

旧方式(NestJS 10):

1
2
3
4
5
6
7
8
CacheModule.registerAsync({
useFactory: async () => {
const store = await redisStore({
socket: { host: 'localhost', port: 6379 },
});
return { store };
},
}),

新方式(NestJS 11)

1
2
3
4
5
CacheModule.registerAsync({
useFactory: async () => ({
stores: [new KeyvRedis('redis://localhost:6379')],
}),
}),

Node.js 版本要求

  • Node.js 16 已不再支持(于 2023-09-11 结束生命周期)。

  • Node.js 18 也被移除(安全支持将于 2025-04-30 结束)。

  • NestJS 11 需要 Node.js 20 或更高版本

建议

始终使用 最新的 LTS 版本 以获得最佳体验。

其他

Mau 是 NestJS 官方推出的云端部署平台

  • 一键部署到 AWS

  • 环境变量管理

  • 实时应用监控

  • 无需管理基础设施

1
2
3
4
5
# 安装
npm install -g @nestjs/mau

# 部署
mau deploy