企业级 NestJS 项目完整指南
上一篇文章,我已经初步验证了 nest 框架的运行效果。但是我现在想要的是真正实战过程中的 nest 框架,它还需要做哪些配置?做哪些代码调整?能实现哪些功能?需要引入哪些插件或者第三方组件?它最终会成为具有什么样功能的项目?
本文档是 Nest 实战的第二篇,主要介绍 Nest 框架的配置、代码调整、功能实现、插件引入以及第三方组件的引入。也就是Nest 高级篇。
Github 项目地址(DEMO)
一、基础架构增强
1. 项目结构规范化
src/
├── common/ # 公共模块
│ ├── decorators/ # 自定义装饰器
│ ├── guards/ # 守卫
│ ├── filters/ # 异常过滤器
│ ├── interceptors/# 拦截器
│ └── middleware/ # 中间件
├── config/ # 配置文件
├── database/ # 数据库相关
├── modules/ # 业务模块
├── shared/ # 共享模块
└── utils/ # 工具函数二、必须的配置和插件
1. 环境配置管理
bash
npm install @nestjs/config cross-envtypescript
// .env
NODE_ENV=development
PORT=3333
DATABASE_URL=mysql://user:password@localhost:3306/db
REDIS_URL=redis://localhost:6379
JWT_SECRET=bob-588typescript
// main.ts
import { NestFactory } from "@nestjs/core";
import { ValidationPipe } from "@nestjs/common";
import { AppModule } from "./app.module";
import { ConfigService } from "./config/config.service";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 全局验证管道
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
})
);
// 获取配置服务
const configService = app.get(ConfigService);
// 验证必需的环境变量
configService.validateRequired([
"NODE_ENV",
"PORT",
"DATABASE_URL",
"REDIS_URL",
"JWT_SECRET",
]);
// 启用CORS(开发环境)
if (configService.app.isDevelopment) {
app.enableCors({
origin: true,
credentials: true,
});
}
const port = configService.app.port;
await app.listen(port);
console.log(`🚀 应用运行在 ${configService.app.nodeEnv} 模式`);
console.log(`📡 服务地址: http://localhost:${port}`);
console.log(
`💾 数据库: ${configService.database.host}:${configService.database.port}`
);
console.log(
`🔴 Redis: ${configService.redis.host}:${configService.redis.port}`
);
}
bootstrap();2. 数据库集成(TypeORM)
bash
npm install @nestjs/typeorm typeorm mysql2
npm install pg pg-native # PostgreSQL
npm install mongodb # MongoDBtypescript
// database.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { ConfigService } from "../config/config.service";
@Module({
imports: [
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
...configService.typeorm,
// 连接重试配置
retryAttempts: 10,
retryDelay: 3000,
// 连接池配置
extra: {
connectionLimit: 10,
acquireTimeout: 60000,
timeout: 60000,
},
// 时区配置
timezone: "+08:00",
// 字符集
charset: "utf8mb4",
}),
}),
],
exports: [TypeOrmModule],
})
export class DatabaseModule {}3. 数据迁移和种子
bash
npm install typeorm-extensiontypescript
// scripts/migration.ts
import { DataSource } from "typeorm";
import { User } from "../modules/users/user.entity";
export async function seedUsers(dataSource: DataSource) {
const userRepository = dataSource.getRepository(User);
const adminUser = userRepository.create({
username: "admin",
email: "admin@example.com",
password: await hashPassword("admin123"),
role: "admin",
});
await userRepository.save(adminUser);
}三、安全配置
1. 身份验证(JWT)
bash
npm install @nestjs/passport passport passport-local
npm install @nestjs/jwt passport-jwt
npm install bcrypttypescript
// auth.module.ts
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
secret: config.get('JWT_SECRET'),
signOptions: {
expiresIn: config.get('JWT_EXPIRES_IN', '7d'),
},
}),
}),
],
providers: [JwtStrategy, LocalStrategy],
})2. 授权(RBAC)
typescript
// guards/roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.get<string[]>(
'roles',
context.getHandler(),
);
if (!requiredRoles) return true;
const request = context.switchToHttp().getRequest();
const user = request.user;
return requiredRoles.some((role) => user.roles?.includes(role));
}
}
// 使用
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin', 'manager')
@Get('admin-only')
adminOnly() {
return 'Admin access only';
}3. 安全中间件
typescript
// main.ts
import helmet from "helmet";
import rateLimit from "express-rate-limit";
import * as csurf from "csurf";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 安全头部
app.use(helmet());
// 速率限制
app.use(
rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 每个IP限制100个请求
})
);
// CORS配置
app.enableCors({
origin: ["http://localhost:3000", "https://your-domain.com"],
credentials: true,
});
// 防止XSS攻击
app.use((req, res, next) => {
res.setHeader("X-Content-Type-Options", "nosniff");
res.setHeader("X-Frame-Options", "DENY");
res.setHeader("X-XSS-Protection", "1; mode=block");
next();
});
}四、缓存和性能优化
1. Redis 缓存
bash
npm install cache-manager cache-manager-redis-store redistypescript
// cache.module.ts
import { CacheModule } from '@nestjs/cache-manager';
import * as redisStore from 'cache-manager-redis-store';
@Module({
imports: [
CacheModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
store: redisStore,
host: config.get('REDIS_HOST'),
port: config.get('REDIS_PORT'),
ttl: 600, // 10分钟
max: 1000, // 最大缓存数量
}),
}),
],
})2. 响应压缩
bash
npm install compressiontypescript
// main.ts
import * as compression from "compression";
app.use(compression());五、文件处理和上传
bash
npm install multer @types/multer
npm install sharp # 图片处理typescript
// upload.service.ts
import { Injectable } from '@nestjs/common';
import { diskStorage } from 'multer';
import { extname } from 'path';
@Injectable()
export class UploadService {
getMulterConfig() {
return {
storage: diskStorage({
destination: './uploads',
filename: (req, file, callback) => {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
const ext = extname(file.originalname);
callback(null, `${file.fieldname}-${uniqueSuffix}${ext}`);
},
}),
limits: {
fileSize: 5 * 1024 * 1024, // 5MB
},
fileFilter: (req, file, callback) => {
if (!file.originalname.match(/\.(jpg|jpeg|png|gif|pdf|doc|docx)$/)) {
return callback(new Error('只允许上传图片和文档'), false);
}
callback(null, true);
},
};
}
}
// 控制器中使用
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
return {
filename: file.filename,
url: `/uploads/${file.filename}`,
size: file.size,
};
}六、日志系统
bash
npm install winston winston-daily-rotate-file
npm install nest-winstontypescript
// logger.config.ts
import { utilities as nestWinstonModuleUtilities } from 'nest-winston';
import * as winston from 'winston';
import 'winston-daily-rotate-file';
export const winstonConfig = {
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.ms(),
nestWinstonModuleUtilities.format.nestLike('MyApp', {
colors: true,
prettyPrint: true,
}),
),
}),
new winston.transports.DailyRotateFile({
filename: 'logs/application-%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json(),
),
}),
],
};
// 使用
import { WinstonModule } from 'nest-winston';
@Module({
imports: [
WinstonModule.forRoot(winstonConfig),
],
})七、任务调度和队列
bash
npm install @nestjs/schedule bull @nestjs/bull
npm install bull-board # Bull队列管理界面typescript
// tasks.module.ts
import { BullModule } from '@nestjs/bull';
import { ScheduleModule } from '@nestjs/schedule';
@Module({
imports: [
ScheduleModule.forRoot(),
BullModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
redis: {
host: config.get('REDIS_HOST'),
port: config.get('REDIS_PORT'),
},
}),
}),
BullModule.registerQueue({
name: 'email',
limiter: {
max: 100,
duration: 1000,
},
}),
],
})八、API 文档(Swagger)
bash
npm install @nestjs/swagger swagger-ui-expresstypescript
// main.ts
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
async function bootstrap() {
const config = new DocumentBuilder()
.setTitle("API文档")
.setDescription("企业级API接口文档")
.setVersion("1.0")
.addBearerAuth()
.addTag("users", "用户管理")
.addTag("auth", "认证授权")
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup("api/docs", app, document);
}九、监控和健康检查
bash
npm install @nestjs/terminus @godaddy/terminus
npm install @nestjs/mongoose mongoose # 如果需要MongoDB监控typescript
// health.module.ts
import { TerminusModule } from '@nestjs/terminus';
import { HttpModule } from '@nestjs/axios';
@Module({
imports: [
TerminusModule.forRoot({
errorLogStyle: 'pretty',
gracefulShutdownTimeoutMs: 1000,
}),
HttpModule,
],
controllers: [HealthController],
})十、测试配置
typescript
// test/setup.ts
import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import * as request from "supertest";
import { AppModule } from "../src/app.module";
describe("AppController (e2e)", () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
it("/users (GET)", () => {
return request(app.getHttpServer()).get("/users").expect(200);
});
});十一、Docker 部署配置
dockerfile
# Dockerfile
FROM node:18-alpine AS development
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine AS production
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=development /usr/src/app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/main"]yaml
# docker-compose.yml
version: "3.8"
services:
app:
build:
context: .
target: production
ports:
- "3000:3000"
environment:
NODE_ENV: production
DATABASE_URL: mysql://user:pass@db:3306/app
depends_on:
- db
- redis
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: app
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
volumes:
mysql_data:
redis_data:十二、最终项目功能清单
一个完整的企业级 NestJS 项目通常包含:
✅ 核心功能
- 用户系统(注册、登录、权限管理)
- JWT 认证 + Refresh Token
- RBAC 权限控制
- 文件上传(本地+云存储)
- 邮件服务(通知、验证码)
- 短信服务(阿里云/腾讯云)
- 支付集成(支付宝、微信支付)
- 第三方登录(微信、QQ、GitHub)
✅ 高级特性
- 微服务架构(gRPC/TCP)
- WebSocket 实时通信
- GraphQL API
- SSR 服务端渲染
- 国际化 i18n
- 多租户支持
- 数据导出(Excel、PDF)
- API 限流和防刷
✅ DevOps 支持
- CI/CD 配置(GitHub Actions/Jenkins)
- 容器化部署(Docker + K8s)
- 性能监控(APM 工具)
- 错误追踪(Sentry)
- 日志聚合(ELK/Logstash)
- API 网关(Kong/Traefik)
十三、最佳实践建议
- 使用 DTO 进行数据验证和转换
- 实现 Repository 模式(避免 Service 直接操作数据库)
- 使用 DTO Mapper(如 class-transformer)
- 实现软删除(isDeleted 字段)
- 数据分页标准化
- 统一响应格式
- 全局异常处理
- 请求 ID 跟踪
- API 版本管理
- 配置中心化
十四、项目启动脚本
json
{
"scripts": {
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"format": "prettier --write \"src/**/*.ts\"",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:e2e": "jest --config ./test/jest-e2e.json",
"typeorm": "ts-node ./node_modules/typeorm/cli",
"migration:generate": "npm run typeorm migration:generate",
"migration:run": "npm run typeorm migration:run",
"seed": "ts-node scripts/seed.ts",
"build": "nest build",
"docker:build": "docker build -t myapp .",
"docker:up": "docker-compose up -d",
"docker:down": "docker-compose down"
}
}总结
一个企业级 NestJS 项目应该是:
- 可扩展的:模块化设计,易于添加新功能
- 可维护的:清晰的代码结构,完善的文档
- 高性能的:缓存、数据库优化、负载均衡
- 安全的:完善的认证授权、输入验证、安全防护
- 可监控的:完整的日志、性能监控、健康检查
- 易部署的:容器化、CI/CD、环境配置




