1. Node.js开发环境搭建全攻略
作为JavaScript运行时环境,Node.js让前端开发者能够用熟悉的语言进行后端开发。我2015年第一次接触Node.js时,就被它的非阻塞I/O模型和事件驱动机制所吸引。经过多年实践,我总结出一套高效的开发环境配置方案,特别适合刚入门的新手。
1.1 版本管理工具选择
我强烈推荐使用nvm(Node Version Manager)来管理Node.js版本。相比直接安装官方包,nvm有以下优势:
- 多版本并行切换(适合不同项目需求)
- 无需sudo权限安装全局包
- 自动处理PATH环境变量
Windows用户可以使用nvm-windows,这是nvm的Windows移植版。安装命令如下:
# Mac/Linux curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash # Windows (管理员权限运行) choco install nvm注意:安装完成后需要重启终端才能生效。我遇到过不少新手因为没重启终端而以为安装失败的情况。
1.2 LTS与Current版本的选择
Node.js有LTS(长期支持)和Current(最新特性)两个版本分支。根据我的经验:
- 生产环境:务必选择LTS版本(当前是20.x)
- 学习环境:可以尝试Current版本体验最新特性
安装特定版本的命令示例:
nvm install 20.9.0 # 安装指定版本 nvm use 20.9.0 # 切换版本 nvm alias default 20.9.0 # 设置默认版本1.3 验证安装结果
安装完成后,运行以下命令验证:
node -v # 查看Node.js版本 npm -v # 查看npm版本如果遇到"command not found"错误,通常是环境变量问题。可以尝试:
source ~/.bashrc # 或 ~/.zshrc2. 开发工具链配置
2.1 代码编辑器选择
我测试过多种编辑器,最终推荐组合:
- VS Code:轻量级、插件丰富
- WebStorm:功能全面但较重量级
VS Code必装插件:
- ESLint:代码规范检查
- Prettier:代码格式化
- REST Client:API测试
- Docker:容器管理
2.2 终端增强
现代Node.js开发离不开好用的终端:
- Mac:iTerm2 + Oh My Zsh
- Windows:Windows Terminal + PowerShell
配置建议:
# .zshrc 添加以下别名 alias nr="npm run" alias ni="npm install" alias ns="npm start"2.3 包管理优化
npm的默认源在国内可能较慢,建议:
# 切换淘宝源 npm config set registry https://registry.npmmirror.com # 安装cnpm(可选) npm install -g cnpm --registry=https://registry.npmmirror.com经验:不要混用npm和cnpm,同一项目保持统一,否则可能导致依赖冲突。
3. 项目初始化与架构设计
3.1 初始化新项目
mkdir my-project cd my-project npm init -y初始化后会生成package.json文件。我建议立即添加以下脚本:
{ "scripts": { "start": "node src/index.js", "dev": "nodemon src/index.js", "test": "jest" } }3.2 基础目录结构
经过多个项目实践,我总结出如下结构:
project/ ├── src/ │ ├── controllers/ # 控制器 │ ├── models/ # 数据模型 │ ├── routes/ # 路由定义 │ ├── services/ # 业务逻辑 │ ├── utils/ # 工具函数 │ └── index.js # 入口文件 ├── tests/ # 测试代码 ├── config/ # 配置文件 ├── .env # 环境变量 └── package.json3.3 基础依赖安装
现代Node.js项目必备依赖:
npm install express dotenv cors npm install --save-dev nodemon eslint prettier4. Express框架实战开发
4.1 创建基础服务器
// src/index.js require('dotenv').config(); const express = require('express'); const cors = require('cors'); const app = express(); const PORT = process.env.PORT || 3000; // 中间件 app.use(cors()); app.use(express.json()); // 测试路由 app.get('/', (req, res) => { res.json({ message: 'Hello Node.js!' }); }); app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); });启动服务器:
npm run dev4.2 路由模块化
我习惯将路由拆分为独立文件:
// src/routes/userRoutes.js const express = require('express'); const router = express.Router(); router.get('/', (req, res) => { res.json({ users: [] }); }); module.exports = router;然后在主文件中引入:
// src/index.js const userRoutes = require('./routes/userRoutes'); app.use('/api/users', userRoutes);4.3 错误处理中间件
健壮的应用需要统一的错误处理:
// src/middlewares/errorHandler.js module.exports = (err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: 'Something went wrong!' }); }; // 在index.js中使用 app.use(require('./middlewares/errorHandler'));5. 数据库集成
5.1 MongoDB连接
我推荐使用mongoose操作MongoDB:
npm install mongoose连接配置:
// src/db/connect.js const mongoose = require('mongoose'); const connectDB = async () => { try { await mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true }); console.log('MongoDB Connected...'); } catch (err) { console.error(err.message); process.exit(1); } }; module.exports = connectDB;5.2 定义数据模型
// src/models/User.js const mongoose = require('mongoose'); const UserSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true } }); module.exports = mongoose.model('User', UserSchema);5.3 CRUD操作示例
// src/controllers/userController.js const User = require('../models/User'); exports.getUsers = async (req, res) => { try { const users = await User.find(); res.json(users); } catch (err) { res.status(500).json({ message: err.message }); } };6. 项目优化与部署
6.1 环境变量管理
使用dotenv管理敏感信息:
# .env PORT=3000 MONGO_URI=mongodb://localhost:27017/myapp JWT_SECRET=your_secret_key重要:务必把.env加入.gitignore!
6.2 性能优化技巧
- 使用helmet增强安全性:
npm install helmetapp.use(require('helmet')());- 启用gzip压缩:
npm install compressionapp.use(require('compression')());6.3 PM2生产环境部署
安装PM2进程管理器:
npm install -g pm2启动应用:
pm2 start src/index.js --name my-app常用命令:
pm2 list # 查看进程 pm2 logs # 查看日志 pm2 restart all # 重启所有进程7. 常见问题解决
7.1 EADDRINUSE错误
端口被占用时会出现这个错误。解决方案:
# Linux/Mac lsof -i :3000 kill -9 <PID> # Windows netstat -ano | findstr :3000 taskkill /PID <PID> /F7.2 依赖安装失败
常见原因和解决方案:
- 权限问题:
# 不要使用sudo! npm config set prefix ~/.npm-global- 网络问题:
npm config set registry https://registry.npmmirror.com- 缓存问题:
npm cache clean --force rm -rf node_modules package-lock.json npm install7.3 ES模块与CommonJS混用
从Node.js v12开始支持ES模块,两种模块系统混用时容易出错。解决方案:
- 统一使用CommonJS(推荐):
// package.json { "type": "commonjs" }- 或者明确文件扩展名:
- .mjs → ES模块
- .cjs → CommonJS
8. 现代Node.js开发进阶
8.1 TypeScript集成
npm install --save-dev typescript @types/node @types/express npx tsc --init配置tsconfig.json:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true } }8.2 单元测试配置
使用Jest测试框架:
npm install --save-dev jest ts-jest @types/jest配置jest.config.js:
module.exports = { preset: 'ts-jest', testEnvironment: 'node', testMatch: ['**/__tests__/**/*.test.ts'] };示例测试:
// __tests__/math.test.ts describe('Math operations', () => { it('should add two numbers correctly', () => { expect(1 + 1).toBe(2); }); });8.3 容器化部署
创建Dockerfile:
FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm install --production COPY . . EXPOSE 3000 CMD ["node", "dist/index.js"]构建和运行:
docker build -t my-node-app . docker run -p 3000:3000 -d my-node-app9. 项目实战:构建RESTful API
9.1 用户认证系统
使用JWT实现认证:
npm install jsonwebtoken bcryptjs npm install --save-dev @types/jsonwebtoken @types/bcryptjs认证中间件:
// src/middlewares/auth.ts import jwt from 'jsonwebtoken'; import { Request, Response, NextFunction } from 'express'; export const auth = (req: Request, res: Response, next: NextFunction) => { const token = req.header('x-auth-token'); if (!token) return res.status(401).json({ message: 'No token, authorization denied' }); try { const decoded = jwt.verify(token, process.env.JWT_SECRET!); req.user = decoded; next(); } catch (err) { res.status(400).json({ message: 'Token is not valid' }); } };9.2 文件上传功能
使用multer处理文件上传:
npm install multer npm install --save-dev @types/multer配置上传中间件:
// src/middlewares/upload.ts import multer from 'multer'; import path from 'path'; const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, 'uploads/'); }, filename: (req, file, cb) => { cb(null, `${Date.now()}-${file.originalname}`); } }); export const upload = multer({ storage, limits: { fileSize: 5 * 1024 * 1024 }, // 5MB fileFilter: (req, file, cb) => { const ext = path.extname(file.originalname).toLowerCase(); if (['.jpg', '.jpeg', '.png'].includes(ext)) { return cb(null, true); } cb(new Error('Only images are allowed')); } });9.3 API文档生成
使用swagger自动生成API文档:
npm install swagger-jsdoc swagger-ui-express配置swagger:
// src/swagger.ts import swaggerJsdoc from 'swagger-jsdoc'; import swaggerUi from 'swagger-ui-express'; const options = { definition: { openapi: '3.0.0', info: { title: 'Node.js API', version: '1.0.0', }, }, apis: ['./src/routes/*.ts'], }; const specs = swaggerJsdoc(options); export default (app: Express) => { app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs)); };10. 性能监控与调试
10.1 日志记录
使用winston进行专业日志记录:
npm install winston配置日志系统:
// src/utils/logger.ts import winston from 'winston'; const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ], }); if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), })); } export default logger;10.2 性能分析
使用clinic.js进行性能分析:
npm install -g clinic常用命令:
clinic doctor -- node src/index.js # 综合诊断 clinic flame -- node src/index.js # 火焰图分析 clinic bubbleprof -- node src/index.js # 异步流程分析10.3 内存泄漏检测
使用heapdump和node-memwatch:
npm install heapdump node-memwatch示例使用:
const heapdump = require('heapdump'); const memwatch = require('node-memwatch'); memwatch.on('leak', (info) => { console.log('Memory leak detected:', info); heapdump.writeSnapshot((err, filename) => { console.log('Heap snapshot written to', filename); }); });11. 项目架构进阶
11.1 分层架构优化
我推荐的三层架构:
- 表现层(Routes):处理HTTP请求/响应
- 业务逻辑层(Services):核心业务逻辑
- 数据访问层(Repositories):数据库操作
示例服务层:
// src/services/userService.ts import UserModel from '../models/User'; class UserService { async createUser(userData) { const user = new UserModel(userData); return await user.save(); } async getUsers() { return await UserModel.find(); } } export default new UserService();11.2 依赖注入实现
使用tsyringe实现IoC:
npm install tsyringe reflect-metadata配置tsconfig.json:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }示例使用:
// src/services/userService.ts import { injectable } from 'tsyringe'; @injectable() export class UserService { // ... } // src/routes/userRoutes.ts import { container } from 'tsyringe'; import { UserService } from '../services/userService'; const userService = container.resolve(UserService);11.3 领域驱动设计(DDD)实践
DDD核心概念在Node.js中的实现:
- 实体(Entities):
// src/domain/user.ts export class User { constructor( public readonly id: string, public name: string, public email: string ) {} }- 值对象(Value Objects):
// src/domain/email.ts export class Email { constructor(public readonly value: string) { if (!this.validate(value)) throw new Error('Invalid email'); } private validate(email: string): boolean { // 验证逻辑 return true; } }- 仓储(Repositories):
// src/repositories/userRepository.ts export interface IUserRepository { save(user: User): Promise<void>; findById(id: string): Promise<User | null>; } // MongoDB实现 export class MongoUserRepository implements IUserRepository { // 实现接口方法 }12. 微服务架构
12.1 gRPC服务实现
安装必要依赖:
npm install @grpc/grpc-js @grpc/proto-loader定义proto文件:
// protos/user.proto syntax = "proto3"; service UserService { rpc GetUser (UserRequest) returns (UserResponse); } message UserRequest { string id = 1; } message UserResponse { string id = 1; string name = 2; string email = 3; }实现服务端:
// src/grpc/server.ts import * as grpc from '@grpc/grpc-js'; import * as protoLoader from '@grpc/proto-loader'; const packageDefinition = protoLoader.loadSync('protos/user.proto'); const userProto = grpc.loadPackageDefinition(packageDefinition); const server = new grpc.Server(); server.addService(userProto.UserService.service, { GetUser: (call, callback) => { // 业务逻辑 callback(null, { id: '1', name: 'Test', email: 'test@example.com' }); } }); server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => { server.start(); });12.2 服务通信
使用axios进行HTTP服务调用:
npm install axios封装服务调用:
// src/services/apiService.ts import axios from 'axios'; class ApiService { private client = axios.create({ baseURL: process.env.API_BASE_URL, timeout: 5000 }); async getUsers() { try { const response = await this.client.get('/users'); return response.data; } catch (error) { throw new Error('Failed to fetch users'); } } } export default new ApiService();12.3 服务发现与负载均衡
使用consul实现服务发现:
npm install consul注册服务示例:
// src/utils/serviceRegistry.ts import consul from 'consul'; const consulClient = consul({ host: process.env.CONSUL_HOST || 'localhost', port: process.env.CONSUL_PORT || '8500' }); export const registerService = () => { const serviceId = `user-service-${process.pid}`; consulClient.agent.service.register({ id: serviceId, name: 'user-service', address: process.env.SERVICE_HOST || 'localhost', port: parseInt(process.env.PORT || '3000'), check: { http: `http://${process.env.SERVICE_HOST || 'localhost'}:${process.env.PORT || '3000'}/health`, interval: '10s', timeout: '5s' } }, () => { console.log('Service registered with Consul'); }); process.on('SIGINT', () => { console.log('Deregistering service...'); consulClient.agent.service.deregister(serviceId, () => { process.exit(); }); }); };13. 安全最佳实践
13.1 常见漏洞防护
- SQL注入防护:
- 使用ORM(如mongoose)自动处理
- 手动查询时使用参数化查询
- XSS防护:
npm install xssimport xss from 'xss'; const clean = xss(userInput);- CSRF防护:
npm install csurfapp.use(require('csurf')({ cookie: true }));13.2 敏感数据保护
- 环境变量加密:
npm install dotenv-vault创建.env.vault:
npx dotenv-vault new npx dotenv-vault push npx dotenv-vault pull production- 数据库字段加密:
npm install mongoose-encryptionimport mongooseEncryption from 'mongoose-encryption'; UserSchema.plugin(mongooseEncryption, { encryptionKey: process.env.ENC_KEY, signingKey: process.env.SIG_KEY, encryptedFields: ['email', 'phone'] });13.3 速率限制
使用express-rate-limit:
npm install express-rate-limit配置示例:
import rateLimit from 'express-rate-limit'; const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100 // 每个IP限制100次请求 }); app.use('/api/', limiter);14. 测试策略
14.1 单元测试进阶
使用Jest模拟mongoose:
npm install --save-dev jest-mock-extended示例测试:
// __tests__/userService.test.ts import { UserService } from '../src/services/userService'; import { mockDeep } from 'jest-mock-extended'; import { Model } from 'mongoose'; describe('UserService', () => { const userModel = mockDeep<Model<any>>(); const userService = new UserService(userModel); it('should create user', async () => { const userData = { name: 'Test', email: 'test@example.com' }; userModel.create.mockResolvedValue(userData); const result = await userService.createUser(userData); expect(result).toEqual(userData); expect(userModel.create).toHaveBeenCalledWith(userData); }); });14.2 集成测试
使用supertest测试API:
npm install --save-dev supertest @types/supertest示例测试:
// __tests__/api.test.ts import request from 'supertest'; import app from '../src/app'; describe('GET /api/users', () => { it('should return 200 OK', async () => { const response = await request(app).get('/api/users'); expect(response.status).toBe(200); expect(response.body).toBeInstanceOf(Array); }); });14.3 E2E测试
使用TestCafe进行端到端测试:
npm install --save-dev testcafe示例测试:
// tests/e2e/userTest.js import { Selector } from 'testcafe'; fixture`User Page`.page`http://localhost:3000/users`; test('Should display user list', async t => { await t .expect(Selector('h1').innerText).eql('Users') .expect(Selector('table tr').count).gt(0); });15. CI/CD流水线
15.1 GitHub Actions配置
创建.github/workflows/node.js.yml:
name: Node.js CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: node-version: '20' - run: npm ci - run: npm run build - run: npm test15.2 Docker多阶段构建
优化后的Dockerfile:
# 构建阶段 FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # 生产阶段 FROM node:20-alpine WORKDIR /app COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY --from=builder /app/package*.json ./ EXPOSE 3000 CMD ["node", "dist/index.js"]15.3 Kubernetes部署
创建deployment.yaml:
apiVersion: apps/v1 kind: Deployment metadata: name: node-app spec: replicas: 3 selector: matchLabels: app: node-app template: metadata: labels: app: node-app spec: containers: - name: node-app image: my-node-app:latest ports: - containerPort: 3000 envFrom: - configMapRef: name: node-app-config创建service.yaml:
apiVersion: v1 kind: Service metadata: name: node-app-service spec: selector: app: node-app ports: - protocol: TCP port: 80 targetPort: 3000 type: LoadBalancer16. 性能优化深度实践
16.1 集群模式
利用多核CPU:
// src/cluster.ts import cluster from 'cluster'; import os from 'os'; import app from './app'; const numCPUs = os.cpus().length; if (cluster.isPrimary) { console.log(`Master ${process.pid} is running`); // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker) => { console.log(`Worker ${worker.process.pid} died`); cluster.fork(); // 自动重启 }); } else { app.listen(3000, () => { console.log(`Worker ${process.pid} started`); }); }16.2 缓存策略
使用Redis缓存:
npm install ioredis缓存中间件示例:
// src/middlewares/cache.ts import Redis from 'ioredis'; const redis = new Redis(process.env.REDIS_URL); export const cache = (key: string, ttl = 60) => { return async (req: Request, res: Response, next: NextFunction) => { const cacheKey = `${key}:${req.originalUrl}`; try { const cached = await redis.get(cacheKey); if (cached) { return res.json(JSON.parse(cached)); } const originalSend = res.send; res.send = function (body) { redis.setex(cacheKey, ttl, JSON.stringify(body)); return originalSend.call(this, body); }; next(); } catch (err) { next(err); } }; };16.3 查询优化
Mongoose查询优化技巧:
- 只选择必要字段:
User.find().select('name email -_id');- 使用lean()跳过hydration:
User.find().lean();- 批量操作:
// 批量插入 User.insertMany(users); // 批量更新 User.bulkWrite([ { updateOne: { filter: { _id: id1 }, update: { $set: { status: 'active' } } } }, { updateOne: { filter: { _id: id2 }, update: { $set: { status: 'inactive' } } } } ]);17. 现代JavaScript特性应用
17.1 ES2023新特性
- 数组findLast/findLastIndex:
const arr = [1, 2, 3, 4, 5]; arr.findLast(x => x % 2 === 0); // 4- Hashbang语法:
#!/usr/bin/env node console.log('Hello from Node.js!');- WeakMap支持Symbol键:
const wm = new WeakMap(); const key = Symbol('key'); wm.set(key, 'value');17.2 顶级await
在ES模块中直接使用await:
// config.js import { readFile } from 'fs/promises'; const config = JSON.parse( await readFile(new URL('./config.json', import.meta.url)) ); export default config;17.3 私有字段与方法
真正的私有成员:
class User { #password; // 私有字段 constructor(name, password) { this.name = name; this.#password = password; } #validate() { // 私有方法 return this.#password.length >= 8; } }18. 调试技巧大全
18.1 Chrome DevTools调试
- 启动调试模式:
node --inspect src/index.js- 在Chrome地址栏输入:
chrome://inspect- 点击"Open dedicated DevTools for Node"
18.2 VSCode调试配置
创建.vscode/launch.json:
{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": ["<node_internals>/**"], "program": "${workspaceFolder}/src/index.js" } ] }18.3 内存泄漏调试
- 生成堆快照:
const heapdump = require('heapdump'); heapdump.writeSnapshot('/tmp/' + Date.now() + '.heapsnapshot');- 使用Chrome DevTools分析快照:
- 比较多个快照
- 查看对象保留树
- 查找DOM泄漏
19. 生态工具推荐
19.1 开发工具
- nodemon:开发时自动重启
- concurrently:并行运行多个命令
- rimraf:跨平台rm -rf
19.2 测试工具
- Jest:全能测试框架
- supertest:API测试
- cypress:E2E测试
19.3 部署工具
- PM2:进程管理
- docker-compose:容器编排
- k6:负载测试
20. 项目实战:全栈应用开发
20.1 前后端分离架构
前端项目结构:
frontend/ ├── public/ ├── src/ │ ├── api/ # API调用 │ ├── assets/ # 静态资源 │ ├── components/# 公共组件 │ ├── pages/ # 页面组件 │ ├── store/ # 状态管理 │ └── App.vue # 根组件后端API设计原则:
- RESTful风格
- 版本控制(/api/v1/)
- 统一的错误格式
20.2 状态管理方案
使用JWT进行认证状态管理:
- 登录流程:
// 前端 const login = async (credentials) => { const res = await axios.post('/api/auth/login', credentials); localStorage.setItem('token', res.data.token); axios.defaults.headers.common['Authorization'] = `Bearer ${res.data.token}`; };- 请求拦截:
axios.interceptors.response.use( response => response, error => { if (error.response.status === 401) { // 跳转到登录页 } return Promise.reject(error); } );20.3 实时功能实现
使用Socket.IO实现实时通信:
后端:
npm install socket.io// src/socket.ts import { Server } from 'socket.io'; export const initSocket = (httpServer) => { const io = new Server(httpServer, { cors: { origin: process.env.CLIENT_URL } }); io.on('connection', (socket) => { console.log('Client connected'); socket.on('message', (msg) => { io.emit('message', msg); }); }); };前端:
import { io } from 'socket.io-client'; const socket = io(process.env.API_URL); socket.on('connect', () => { console.log('Connected to server'); }); socket.on('message', (msg) => { console.log('New message:', msg); });21. 项目文档与协作
21.1 API文档生成
使用OpenAPI规范:
npm install swagger-jsdoc swagger-ui-express配置示例:
// src/swagger.ts import swaggerJsdoc from 'swagger-jsdoc'; const options = { definition: { openapi: '3.0.0', info: { title: 'Node.js API', version: '1.0.0', }, components: { securitySchemes: { bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' } } } }, apis: ['./src/routes/*.ts'], }; export default swaggerJsdoc(options);21.2 提交规范
使用commitlint规范提交信息:
npm install --save-dev @commitlint/config-conventional @commitlint/cli创建commitlint.config.js:
module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', [ 'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'revert' ]], 'subject-case': [0] } };21.3 代码审查
GitHub PR模板示例:
## 变更描述 ## 相关Issue ## 检查清单 - [ ] 已测试 - [ ] 已更新文档 - [ ] 已考虑向后兼容22. 项目监控与告警
22.1 健康检查端点
// src/routes/health.ts import { Router } from 'express'; import mongoose from 'mongoose'; const router = Router(); router.get('/', async (req, res) => { const dbStatus = mongoose.connection.readyState === 1 ? 'connected' : 'disconnected'; res.json({ status: 'up', timestamp: new Date(), db: dbStatus, memoryUsage: process.memoryUsage(), uptime: process