项目结构解析
NestJS 项目初始化后,src/
目录下的结构清晰、职责分明。理解这些文件的作用,是高效开发的第一步。
典型目录结构
my-nest-app/
src/
app.controller.ts // 应用主控制器
app.controller.spec.ts // 控制器单元测试
app.module.ts // 应用主模块
app.service.ts // 应用主服务
main.ts // 应用入口文件
user/ // 用户业务模块
order/ // 订单业务模块
share/ // 共享代码(工具、常量、DTO等)
filters/ // 全局/自定义异常过滤器
decorators/ // 自定义装饰器
interceptors/ // 拦截器(如日志、响应格式化等)
guards/ // 守卫(如权限、认证)
pipes/ // 管道(如参数校验、转换)
middlewares/ // 中间件(如日志、请求追踪)
关键文件说明
-
main.ts
- 应用程序入口,负责启动 Nest 应用。
- 常见操作:端口监听、中间件挂载、全局拦截器/管道注册等。
// main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { LoggingInterceptor } from './interceptors/logging.interceptor'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalInterceptors(new LoggingInterceptor()); // 全局拦截器 await app.listen(3000); console.log('应用已启动:http://localhost:3000'); } bootstrap();
-
app.module.ts
- 应用的根模块,负责组织和导入其他功能模块。
- 通过
@Module
装饰器声明 controllers、providers、imports 等。
// app.module.ts import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { UserModule } from './user/user.module'; import { OrderModule } from './order/order.module'; import { APP_FILTER } from '@nestjs/core'; import { AllExceptionsFilter } from './filters/all-exceptions.filter'; @Module({ imports: [UserModule, OrderModule], controllers: [AppController], providers: [ AppService, { provide: APP_FILTER, useClass: AllExceptionsFilter }, // 全局异常过滤器 ], }) export class AppModule {}
-
app.controller.ts
- 控制器,负责处理路由请求和响应。
- 通过
@Controller
装饰器定义路由前缀,方法上用@Get
、@Post
等装饰器定义接口。
// app.controller.ts import { Controller, Get } from '@nestjs/common'; import { AppService } from './app.service'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() getHello(): string { return this.appService.getHello(); } }
-
app.service.ts
- 服务层,负责业务逻辑处理。
- 通过
@Injectable
装饰器声明,可被控制器等依赖注入。
// app.service.ts import { Injectable } from '@nestjs/common'; @Injectable() export class AppService { getHello(): string { return 'Hello World!'; } }
-
share/
- 存放项目中可复用的工具函数、常量、DTO(数据传输对象)、通用类型等。
- 例如:
// share/constants.ts export const JWT_SECRET = 'my_jwt_secret'; // share/utils.ts export function toResponse(data: any) { return { code: 0, data }; }
-
filters/
- 存放全局或自定义的异常过滤器,统一处理错误响应。
- 例如:
// filters/all-exceptions.filter.ts import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; import { Response } from 'express'; @Catch() export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const status = exception instanceof HttpException ? exception.getStatus() : 500; response.status(status).json({ code: status, message: exception instanceof HttpException ? exception.message : '服务器错误', }); } }
-
decorators/
- 存放自定义装饰器,简化控制器或服务的参数注入、权限校验等。
- 例如:
// decorators/user.decorator.ts import { createParamDecorator, ExecutionContext } from '@nestjs/common'; export const CurrentUser = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user; }, );
-
interceptors/
- 存放拦截器,用于统一处理请求/响应、日志、数据格式化等。
- 例如:
// interceptors/logging.interceptor.ts import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable, tap } from 'rxjs'; @Injectable() export class LoggingInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { const now = Date.now(); return next.handle().pipe( tap(() => console.log(`请求耗时: ${Date.now() - now}ms`)), ); } }
-
guards/
- 存放守卫,用于权限控制、认证等。
- 例如:
// guards/auth.guard.ts import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class AuthGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); return Boolean(request.headers['authorization']); // 简单示例 } }
-
pipes/
- 存放管道,用于参数校验、数据转换等。
- 例如:
// pipes/parse-int.pipe.ts import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; @Injectable() export class ParseIntPipe implements PipeTransform<string, number> { transform(value: string): number { const val = parseInt(value, 10); if (isNaN(val)) { throw new BadRequestException('参数必须为数字'); } return val; } }
-
middlewares/
- 存放中间件,用于日志、请求追踪、跨域等。
- 例如:
// middlewares/logger.middleware.ts import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class LoggerMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { console.log(`[${req.method}] ${req.originalUrl}`); next(); } }
实战场景:快速定位与扩展
假如你要新增一个用户模块,只需在 src/
下新建 user/
目录,并在 app.module.ts
的 imports
中注册即可。清晰的结构让多人协作和后期维护变得非常高效。
常见坑点:
- 忘记在
app.module.ts
注册新模块,导致依赖无法注入。- 控制器或服务命名冲突,建议按功能模块分目录管理。
- 共享代码未统一管理,建议集中放在 share 目录,便于复用和维护。
- 全局过滤器、装饰器、拦截器、守卫、管道未注册或未正确导出,导致功能失效。
- 中间件未在 main.ts 或模块中正确 use,导致请求未被拦截。