NestJS 模板
基于 NestJS + TypeScript 的现代化后端开发模板,支持模块化架构、依赖注入、测试和完整的开发工具链。
技术栈
- NestJS - 基于 Node.js 的企业级应用框架
- TypeScript - JavaScript 的超集,提供类型安全
- Express - 基于 Express 的 HTTP 服务器
- Jest - JavaScript 测试框架
- Docker - 容器化部署
- MariaDB - 开源关系型数据库
- Redis - 内存数据结构存储
快速开始
创建项目
bash
# 初始化项目
vup init my-project
# 进入项目目录
cd my-project
# 添加 NestJS 应用
vup add my-api
# 选择 NestJS 模板
开发
bash
# 安装依赖
pnpm install
# 启动开发服务器(监听文件变化)
pnpm dev:watch
开发服务器将在 http://localhost:9310
启动
构建
bash
# 构建生产版本
pnpm build
# 启动生产服务器
pnpm start:prod
项目结构
my-api/
├── src/
│ ├── app.controller.spec.ts # 控制器测试
│ ├── app.controller.ts # 应用控制器
│ ├── app.module.ts # 应用模块
│ ├── app.service.ts # 应用服务
│ └── main.ts # 应用入口
├── test/
│ ├── app.e2e-spec.ts # 端到端测试
│ └── jest-e2e.json # E2E 测试配置
├── docker-compose.yml # Docker 编排文件
├── nest-cli.json # NestJS CLI 配置
├── package.json # 项目配置
├── tsconfig.json # TypeScript 配置
└── README.md # 项目说明
核心特性
🎯 TypeScript 支持
完整的 TypeScript 支持,提供类型安全和智能提示:
typescript
// 服务中使用 TypeScript
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
🏗️ 模块化架构
基于 NestJS 的模块化架构:
typescript
// 创建新模块
@Module({
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
💉 依赖注入
完整的 IoC 容器支持:
typescript
// 控制器中使用依赖注入
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
🛣️ 路由系统
基于装饰器的路由定义:
typescript
@Controller('users')
export class UsersController {
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(+id);
}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
}
🛡️ 守卫和中间件
认证和授权支持:
typescript
// 创建守卫
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return this.validateRequest(request);
}
}
// 创建中间件
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`${req.method} ${req.path} - ${new Date().toISOString()}`);
next();
}
}
🔄 拦截器和管道
请求/响应拦截和数据验证:
typescript
// 创建拦截器
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
return next.handle();
}
}
// 创建管道
@Injectable()
export class ValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
// 数据验证逻辑
return value;
}
}
开发工具
代码质量
- ESLint - 代码质量检查
- Prettier - 代码格式化
- TypeScript - 类型检查
开发命令
bash
# 开发服务器
pnpm dev:watch # 监听文件变化
pnpm dev # 普通开发模式
pnpm start:debug # 调试模式
# 构建和部署
pnpm build # 构建生产版本
pnpm start:prod # 启动生产服务器
# 测试
pnpm test # 运行单元测试
pnpm test:watch # 监听模式运行测试
pnpm test:cov # 生成测试覆盖率报告
pnpm test:e2e # 运行端到端测试
# 代码质量
pnpm lint # 代码检查
pnpm lint:fix # 自动修复问题
pnpm format # 代码格式化
热重载
NestJS 提供极速的热重载体验:
- 修改 TypeScript 文件时自动重启
- 保持应用状态
- 快速编译和启动
测试支持
单元测试
typescript
// 服务测试
describe('AppService', () => {
let service: AppService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AppService],
}).compile();
service = module.get<AppService>(AppService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should return "Hello World!"', () => {
expect(service.getHello()).toBe('Hello World!');
});
});
E2E 测试
typescript
// 端到端测试
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!');
});
});
Docker 支持
开发环境
bash
# 启动数据库服务
pnpm docker:db
# 启动应用服务
pnpm docker:app
# 启动所有服务
pnpm docker:up
管理服务
bash
# 停止所有服务
pnpm docker:down
# 重新构建镜像
pnpm docker:build
# 查看服务日志
pnpm docker:logs
Docker Compose 配置
yaml
version: '3.8'
services:
mariadb:
image: mariadb:11.3
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
ports:
- '9306:3306'
redis:
image: redis:7.2-alpine
ports:
- '9379:6379'
最佳实践
模块设计
- 按功能划分模块
- 保持模块的单一职责
- 合理使用依赖注入
- 避免循环依赖
控制器设计
- 保持控制器的简洁
- 使用 DTO 进行数据验证
- 合理使用装饰器
- 处理异常情况
服务设计
- 将业务逻辑封装在服务中
- 使用接口定义服务契约
- 保持服务的可测试性
- 避免在服务中处理 HTTP 相关逻辑
测试策略
- 编写单元测试覆盖核心逻辑
- 使用 E2E 测试验证 API 接口
- 保持测试的独立性和可重复性
- 追求合理的测试覆盖率
部署
静态部署
bash
# 构建生产版本
pnpm build
# 启动生产服务器
pnpm start:prod
Docker 部署
dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN pnpm install
COPY . .
RUN pnpm build
EXPOSE 9310
CMD ["pnpm", "start:prod"]
部署到 Vercel
NestJS 应用可以部署到 Vercel。详细的部署配置和步骤请参考 Vercel 部署指南。