前端 + NestJS 全栈实践
概念
NestJS 作为企业级服务端框架,与前端框架配合可以构建完整的全栈应用。核心挑战在于前后端类型共享、API 设计规范、部署协同。
前后端类型共享
Monorepo 结构
my-project/
├── packages/
│ ├── shared/ # 共享类型 + DTO
│ │ ├── src/
│ │ │ ├── types.ts
│ │ │ └── dto/
│ │ └── package.json
│ ├── server/ # NestJS 后端
│ └── client/ # React/Vue 前端
├── pnpm-workspace.yaml
└── package.json1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
typescript
// packages/shared/src/dto/create-user.dto.ts
export class CreateUserDto {
name: string
email: string
age: number
}
export interface UserResponse {
id: string
name: string
email: string
createdAt: string
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
前后端都从 @my-project/shared 导入类型,一处修改全局同步。
API 响应类型
typescript
// 统一的 API 响应格式
export interface ApiResponse<T> {
code: number
message: string
data: T
timestamp: string
}
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
total: number
page: number
pageSize: number
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Swagger / OpenAPI
NestJS 内置 Swagger 支持,自动生成 API 文档:
typescript
const config = new DocumentBuilder()
.setTitle('API 文档')
.setDescription('前端知识宝典 API')
.setVersion('1.0')
.addBearerAuth()
.build()
const document = SwaggerModule.createDocument(app, config)
SwaggerModule.setup('api-docs', app, document)1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
前端可通过 openapi-generator 从 Swagger JSON 自动生成 API 客户端代码。
文件上传
NestJS 使用 Multer 处理文件上传:
typescript
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
// file.originalname, file.buffer, file.size, file.mimetype
return { url: `https://cdn.example.com/${file.filename}` }
}1
2
3
4
5
6
2
3
4
5
6
前端 FormData + fetch/axios:
typescript
const formData = new FormData()
formData.append('file', file)
await fetch('/api/upload', { method: 'POST', body: formData })1
2
3
2
3
实时通信
WebSocket
NestJS 支持 Socket.IO:
typescript
// 服务端
@WebSocketGateway({ cors: true })
export class ChatGateway implements OnGatewayConnection {
@WebSocketServer()
server: Server
@SubscribeMessage('message')
handleMessage(@MessageBody() msg: string): void {
this.server.emit('message', msg)
}
}
// 前端
import { io } from 'socket.io-client'
const socket = io('http://localhost:3000')
socket.on('message', (msg) => console.log(msg))1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SSE(Server-Sent Events)
typescript
@Sse('events')
sendEvents(): Observable<MessageEvent> {
return interval(1000).pipe(
map(() => ({ data: { time: new Date().toISOString() } })),
)
}1
2
3
4
5
6
2
3
4
5
6
部署
Nginx 反代 → NestJS (PM2 cluster) → PostgreSQL/Redis
↑
前端静态资源(Nginx 直接托管)1
2
3
2
3
Docker 化:
dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --prod
COPY dist ./dist
EXPOSE 3000
CMD ["node", "dist/main.js"]1
2
3
4
5
6
7
2
3
4
5
6
7
面试常问
- 前后端共享 DTO 类型的最佳实践?类型不同步如何保障?
- Swagger 对于前后端协作的价值?
- NestJS 生产部署需要考虑哪些因素?
