
1. NestJS框架概述为什么选择它NestJS是一个基于Node.js的渐进式框架用于构建高效、可靠的服务器端应用程序。它采用TypeScript作为主要开发语言结合了面向对象编程OOP、函数式编程FP和响应式编程RP的最佳实践。我在实际项目中使用NestJS已有三年多时间发现它特别适合构建企业级应用。提示NestJS的核心设计理念借鉴了Angular的架构思想如果你有Angular开发经验会更容易上手。框架的核心优势在于其模块化设计。通过Module装饰器你可以将应用程序划分为多个功能模块每个模块包含自己的控制器、服务和其他依赖项。这种设计使得代码组织更加清晰也便于团队协作开发。2. 快速搭建NestJS开发环境2.1 安装必备工具首先需要安装Node.js建议v16和npm/yarn。我推荐使用nvm来管理Node版本curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash nvm install 16 nvm use 16然后安装Nest CLI工具npm i -g nestjs/cli2.2 创建新项目使用CLI创建项目非常简单nest new my-project cd my-project npm run start:dev这个命令会创建一个标准NestJS项目结构src/ ├── app.controller.ts ├── app.module.ts ├── app.service.ts └── main.ts注意如果你看到Unable to find nestjs/common错误可能是node_modules安装不完整删除后重新npm install即可。3. 核心概念深度解析3.1 模块系统设计模块是NestJS的基本组织单元。一个典型的模块定义如下Module({ imports: [OtherModule], controllers: [AppController], providers: [AppService], exports: [AppService] }) export class AppModule {}imports声明本模块依赖的其他模块controllers注册本模块的控制器providers注册本模块的服务exports暴露本模块的服务给其他模块使用3.2 依赖注入机制NestJS内置了强大的DI容器。通过构造函数注入服务Controller() export class AppController { constructor(private readonly appService: AppService) {} Get() getHello(): string { return this.appService.getHello(); } }这种设计使得单元测试更加容易你可以轻松地mock依赖项。4. 实战构建REST API4.1 创建资源模块使用CLI快速生成资源nest g resource users这会生成完整的CRUD模板包括users.controller.tsusers.module.tsusers.service.tsDTO和实体文件4.2 数据库集成我推荐使用TypeORM与NestJS配合Module({ imports: [ TypeOrmModule.forRoot({ type: postgres, host: localhost, port: 5432, username: postgres, password: password, database: test, entities: [User], synchronize: true, }), UsersModule ], }) export class AppModule {}然后在User实体中定义模型Entity() export class User { PrimaryGeneratedColumn() id: number; Column() name: string; }5. 高级特性与最佳实践5.1 中间件与拦截器NestJS提供了多种请求处理管道// 日志中间件 Injectable() export class LoggerMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { console.log([${new Date().toISOString()}] ${req.method} ${req.url}); next(); } } // 响应拦截器 Injectable() export class TransformInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observableany { return next.handle().pipe( map(data ({ data, code: 0, message: success })) ); } }5.2 配置管理推荐使用nestjs/config管理环境变量Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath: .env.${process.env.NODE_ENV} }), ], }) export class AppModule {}然后在服务中注入Injectable() export class AppService { constructor(private configService: ConfigService) {} getHello(): string { const dbHost this.configService.getstring(DB_HOST); return Hello from ${dbHost}; } }6. 性能优化技巧6.1 启用压缩安装compression中间件npm i compression然后在main.ts中使用import * as compression from compression; async function bootstrap() { const app await NestFactory.create(AppModule); app.use(compression()); await app.listen(3000); }6.2 缓存策略使用CacheModule提高性能Module({ imports: [ CacheModule.register({ ttl: 5, // 缓存5秒 max: 10 // 最大缓存数 }), ], }) export class AppModule {}在控制器中使用Controller() UseInterceptors(CacheInterceptor) export class AppController { Get() CacheKey(custom_key) getHello(): string { return this.appService.getHello(); } }7. 常见问题排查7.1 依赖注入错误如果遇到Provider not found错误检查服务是否标记为Injectable()服务是否在模块的providers数组中注册模块是否被正确导入7.2 跨域问题在main.ts中启用CORSapp.enableCors({ origin: [http://localhost:3000], methods: GET,HEAD,PUT,PATCH,POST,DELETE, credentials: true, });7.3 性能瓶颈使用async_hooks监控请求处理时间import { AsyncLocalStorage } from async_hooks; const asyncLocalStorage new AsyncLocalStorage(); app.use((req, res, next) { const store { startTime: Date.now() }; asyncLocalStorage.run(store, () next()); }); // 在拦截器中获取 const store asyncLocalStorage.getStore(); console.log(Request took ${Date.now() - store.startTime}ms);8. 项目结构建议经过多个项目实践我总结出以下目录结构src/ ├── common/ # 公共模块 │ ├── filters/ # 异常过滤器 │ ├── interceptors # 拦截器 │ └── pipes/ # 管道 ├── config/ # 配置文件 ├── modules/ # 业务模块 │ ├── auth/ # 认证模块 │ ├── users/ # 用户模块 │ └── ... ├── app.module.ts # 根模块 └── main.ts # 入口文件这种结构保持了良好的可扩展性当项目规模增长时依然易于维护。9. 测试策略9.1 单元测试使用Jest测试服务describe(AppService, () { let service: AppService; beforeEach(async () { const module: TestingModule await Test.createTestingModule({ providers: [AppService], }).compile(); service module.getAppService(AppService); }); it(should return Hello World, () { expect(service.getHello()).toBe(Hello World); }); });9.2 E2E测试测试整个应用describe(AppController (e2e), () { let app: INestApplication; beforeEach(async () { const moduleFixture: TestingModule await Test.createTestingModule({ imports: [AppModule], }).compile(); app moduleFixture.createNestApplication(); await app.init(); }); it(/ (GET), () { return request(app.getHttpServer()) .get(/) .expect(200) .expect(Hello World); }); });10. 部署方案10.1 传统部署构建生产版本npm run build然后使用PM2运行pm2 start dist/main.js --name my-nest-app10.2 Docker部署创建DockerfileFROM node:16-alpine WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build EXPOSE 3000 CMD [node, dist/main.js]构建并运行docker build -t my-nest-app . docker run -p 3000:3000 my-nest-app11. 监控与日志11.1 健康检查安装terminusnpm i nestjs/terminus设置健康端点Controller(health) export class HealthController { constructor( private health: HealthCheckService, private db: TypeOrmHealthIndicator, ) {} Get() HealthCheck() check() { return this.health.check([ () this.db.pingCheck(database), ]); } }11.2 结构化日志使用winstonconst winstonLogger winston.createLogger({ level: info, format: winston.format.json(), transports: [ new winston.transports.File({ filename: error.log, level: error }), ], }); const app await NestFactory.create(AppModule, { logger: WinstonModule.createLogger({ instance: winstonLogger, }), });12. 微服务架构NestJS原生支持微服务// main.ts const app await NestFactory.createMicroservice(AppModule, { transport: Transport.TCP, options: { host: localhost, port: 3001 }, }); // 客户端 Client({ transport: Transport.TCP, options: { host: localhost, port: 3001 }, }) client: ClientProxy;13. 安全最佳实践13.1 Helmet防护安装helmetnpm i helmet在main.ts中使用import * as helmet from helmet; app.use(helmet());13.2 速率限制安装throttlernpm i nestjs/throttler配置模块Module({ imports: [ ThrottlerModule.forRoot({ ttl: 60, limit: 10, }), ], }) export class AppModule {}保护路由UseGuards(ThrottlerGuard) Get() findAll() { return this.service.findAll(); }14. 实际项目经验分享在最近的一个电商项目中我们使用NestJS处理了日均100万的请求量。几个关键经验数据库连接池配置很重要我们使用以下配置TypeOrmModule.forRoot({ extra: { connectionLimit: 20, queueLimit: 100, }, })对于高并发接口我们实现了本地缓存Redis二级缓存Injectable() export class ProductService { private localCache new Map(); async getProduct(id: number) { if (this.localCache.has(id)) { return this.localCache.get(id); } const product await this.redis.get(product:${id}) || await this.productRepo.findOne(id); this.localCache.set(id, product); return product; } }使用拦截器统一处理响应和错误Injectable() export class ResponseInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observableany { return next.handle().pipe( map(data ({ data })), catchError(err { const response context.switchToHttp().getResponse(); response.status(err.status || 500); return throwError(() ({ code: err.code || -1, message: err.message, timestamp: new Date().toISOString() })); }) ); } }