项目技术栈与开发规范
📋 目录导航
- 核心技术栈
- 安全架构设计原则
- 项目结构与代码规范
- 核心代码实现模板
- 架构优势与开发策略
- 请求AI协助时的示例格式
- 版本控制与部署规范
- 环境配置与脚本规范
- 代码质量检查与验证规范
- 错误处理与文档维护规范
- 完整项目生命周期管理
1. 核心技术栈
📌 重要说明: 以下是我们项目使用的核心技术栈。所有代码生成和技术方案都必须严格遵守此规范。
🔧 可选组件说明: 标记为"可选"的组件可根据项目需求和开发阶段灵活选择是否启用。
以下是我们项目使用的核心技术栈:
- 应用框架: Next.js 15+
- 角色: 全栈Web框架。
- 规范:
- 路由: 严格使用 App Router (
/src/app目录结构)。 - 组件: 默认使用 React Server Components (RSC) 进行数据获取和后端逻辑处理。仅在需要交互性时(如
onClick,useState)使用'use client'声明客户端组件。 - 数据交互: 优先使用 Server Actions 处理表单提交和数据变更 (Mutations)。
- 路由: 严格使用 App Router (
- 认证: NextAuth.js
- 角色: 处理用户认证和会话管理。
- 规范: 与中间件集成,提供用户身份信息给安全架构使用。
- UI & 样式:
- 组件库: shadcn/ui
- 角色: 提供基础UI组件。
- 规范: 组件通过CLI安装到项目
/src/components/ui目录中,可直接进行修改。 - 参考: https://www.shadcn.com.cn/docs/components/accordion
- CSS框架: Tailwind CSS
- 角色: 用于所有样式定义。
- 规范: 采用原子化CSS类进行样式编写。避免使用原生CSS文件,除非用于全局基础样式定义 (
/src/app/globals.css)。
- 组件库: shadcn/ui
- AI 核心: Vercel AI SDK
- 角色: 连接前端与大型语言模型 (LLM) API的桥梁。
- 规范:
- 使用其提供的React Hooks (如
useChat,useCompletion) 在客户端组件中实现流式响应。 - 在Server Actions或Route Handlers中调用其核心函数,与AI模型进行交互。
- 使用其提供的React Hooks (如
- 数据库: PostgreSQL (with
pgvectorextension)- 角色: 主数据库,用于存储结构化数据和向量数据。
- 规范: 必须启用并使用
pgvector扩展来支持向量的存储和相似度搜索。 - 安全: 启用行级安全 (Row-Level Security, RLS) 确保数据访问权限在数据库层面强制执行。
- ORM: Prisma
- 角色: 数据库访问层,提供类型安全的数据库操作。便于拓展。
- 规范:
- 模型定义: 唯一的真实数据源是
/prisma/schema.prisma文件。所有数据模型必须在此文件中定义。 - 工作流:
- 修改
schema.prisma文件。 - 本地开发运行
npx prisma generate来更新Prisma Client类型。 - 本地开发运行
npx prisma migrate dev来创建和应用数据库迁移。
- 修改
- 客户端实例: 在
/src/lib/prisma.ts中创建并导出一个单例的PrismaClient实例,以避免在开发环境中创建过多连接。 - 安全扩展: 使用 Prisma 客户端扩展 (
$extends) 集成安全上下文。
- 模型定义: 唯一的真实数据源是
- 缓存/性能 (可选): Redis
- 角色: 高性能缓存层,用于优化数据访问性能。
- 规范: 在服务层预留缓存逻辑,支持"即插即用"的性能优化。
- 说明: 🔧 可选组件 - 项目初期可不配置,后期根据性能需求决定是否启用。
- 静态文件存储: 阿里云 OSS (S3 兼容)
- 角色: 存储用户上传的图片、视频、文档等静态资源。
- 规范:
- 应用后端通过 S3 兼容的SDK (例如
@aws-sdk/client-s3) 与 OSS 进行交互。 - 客户端上传文件时,应通过后端获取预签名的上传URL (presigned URL) 来实现安全、直接的上传,避免文件流经服务器。
- 数据库中只存储文件的 key 或 URL,不存储文件本身。
- 应用后端通过 S3 兼容的SDK (例如
2. 安全架构设计原则
2.1 目标与愿景
本项目采用一种在现代Web应用中实现健壮、可维护、高性能且对开发者友好的数据架构方案。其核心目标是:
- 极致安全: 数据访问权限在数据库层面强制执行(RLS),确保用户只能访问其自身拥有的数据。
- 关注点分离:
- API路由/页面 负责处理HTTP请求与响应。
- 服务层 负责封装和集中化所有业务逻辑与数据访问策略。
- 数据层 (Prisma/PostgreSQL) 负责数据的持久化与安全过滤。
- 性能就绪 (Performance-Ready): 架构从第一天起就为引入缓存(如 Redis)预留了位置,未来可无缝激活性能优化,而无需重构。
- 卓越的开发体验 (DX): 业务代码简洁、直观,无需关心底层的RLS实现或数据来源(数据库/缓存)。
2.2 请求生命周期
一个受保护的请求从发起到响应的完整流程如下:
- [请求入口] Next.js Middleware:
- 拦截请求,解析用户身份 (
userId)。 - 将
userId注入到AsyncLocalStorage上下文中,供后续调用链使用。
- 拦截请求,解析用户身份 (
- [调用层] API 路由 / Server Component:
- 职责非常单一:处理HTTP层的事务(解析请求体、返回JSON响应等)。
- 它不再直接与
prisma交互,而是调用服务层中定义好的函数来完成业务需求。例如await postService.getPostsForCurrentUser()。
- [服务层] 数据服务 / 业务逻辑封装:
- 架构的核心。所有业务逻辑和数据访问被封装在此处(例如
services/postService.ts)。 - 它是数据来源的决策者。这里是为Redis预留的位置。它会决定是从缓存(未来)还是从数据库获取数据。
- 它调用
prisma客户端来执行数据库操作。
- 架构的核心。所有业务逻辑和数据访问被封装在此处(例如
- [数据访问层] Prisma Client Extension:
- 服务层调用
prisma时,增强的Client Extension会被触发。 - 它从
AsyncLocalStorage中读取userId,并通过事务安全地设置PostgreSQL的会话变量app.current_user_id。
- 服务层调用
- [数据库层] PostgreSQL RLS 执行:
- PostgreSQL 根据会话变量和预设的RLS策略,在底层完成数据过滤。
- [响应] 返回安全数据:
- 安全的数据沿调用链原路返回:
PostgreSQL -> Prisma -> 服务层 -> 调用层 -> 客户端。
- 安全的数据沿调用链原路返回:
3. 项目结构与代码规范
📁 架构: 基于 Next.js 15 App Router 的现代化项目结构
🎯 原则: 清晰分层、职责分离、易于维护和扩展
🔧 类型安全: 严格的 TypeScript 配置,禁止使用 any 类型
- 语言: TypeScript (启用
strict模式,必须提醒AI编写时严禁使用ANY类型)。 - 主要目录结构:
/ ├── prisma/ │ └── schema.prisma # 数据库模型定义 ├── public/ # 静态资源 └── src/ ├── app/ # Next.js 路由和页面 │ ├── api/ # API Route Handlers │ └── (routes)/... # 页面组件 ├── components/ │ ├── ui/ # shadcn/ui 官方组件 │ └── shared/ # 项目自定义的、可复用的组件 ├── services/ # 业务逻辑服务层 │ └── *.ts # 各种业务服务 (如 postService.ts) └── lib/ ├── prisma.ts # Prisma Client 单例 (带安全扩展) ├── context.ts # 请求上下文管理 ├── redis.ts # Redis 客户端 (预留) ├── ai.ts # AI SDK 相关配置和助手函数 ├── oss.ts # OSS/S3 客户端和相关函数 └── utils.ts # 通用工具函数
4. 核心代码实现模板
4.1 PostgreSQL 安全规则
-- 1. 在需要保护的表上启用 RLS
ALTER TABLE "public"."Post" ENABLE ROW LEVEL SECURITY;
-- 2. 创建具体的安全策略
-- 只允许用户读取、创建、修改、删除自己的帖子
CREATE POLICY "user_can_manage_own_posts"
ON "public"."Post" FOR ALL
USING ("authorId"::text = current_setting('app.current_user_id', true))
WITH CHECK ("authorId"::text = current_setting('app.current_user_id', true));
4.2 请求上下文管理 (lib/context.ts)
// lib/context.ts
import { AsyncLocalStorage } from 'async_hooks';
export interface RequestContext {
userId: string;
}
// 全局唯一的上下文存储实例
export const requestContextStore = new AsyncLocalStorage<RequestContext>();
// 用于在代码中安全获取上下文的辅助函数
export function getRequestContext(): RequestContext {
const context = requestContextStore.getStore();
if (!context) {
throw new Error('请求上下文未找到。请确保请求已被中间件处理。');
}
return context;
}
4.3 增强的 Prisma Client (lib/prisma.ts)
// lib/prisma.ts
import { PrismaClient } from '@prisma/client';
import { getRequestContext } from './context';
const prismaClientSingleton = () => {
return new PrismaClient().$extends({
query: {
$allModels: {
async $allOperations({ args, query }) {
try {
const { userId } = getRequestContext();
const [_, result] = await prisma.$transaction([
prisma.$executeRawUnsafe(`SET app.current_user_id = '${userId}'`),
query(args),
]);
return result;
} catch (error) {
// 如果没有上下文(例如在后台任务中),直接执行查询
// 让数据库的 RLS 策略根据规则去拒绝或放行
return query(args);
}
},
},
},
});
};
declare global {
var prisma: undefined | ReturnType<typeof prismaClientSingleton>;
}
// 导出一个全局唯一的、增强后的 prisma 实例
export const prisma = globalThis.prisma ?? prismaClientSingleton();
if (process.env.NODE_ENV !== 'production') {
globalThis.prisma = prisma;
}
4.4 中间件配置 (middleware.ts)
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getToken } from 'next-auth/jwt';
import { requestContextStore } from '@/lib/context';
export async function middleware(request: NextRequest) {
const token = await getToken({ req: request });
const userId = token?.sub;
if (userId) {
// 为整个请求的生命周期运行在带有 userId 的上下文中
return await requestContextStore.run({ userId }, () => {
return NextResponse.next();
});
}
return NextResponse.next();
}
export const config = {
matcher: ['/api/:path*', '/dashboard/:path*'], // 根据需要保护的路径配置
};
4.5 Redis 客户端预留 (lib/redis.ts)
// lib/redis.ts
import Redis from 'ioredis';
const redisClientSingleton = () => {
if (process.env.REDIS_URL) {
console.log('正在初始化 Redis 客户端...');
return new Redis(process.env.REDIS_URL);
}
console.warn('未找到 REDIS_URL,Redis 客户端未初始化。');
return null;
};
declare global {
var redis: undefined | Redis | null;
}
// 导出一个全局唯一的 Redis 客户端实例
export const redis = globalThis.redis ?? redisClientSingleton();
if (process.env.NODE_ENV !== 'production') {
globalThis.redis = redis;
}
4.6 服务层模板 (services/postService.ts)
// services/postService.ts
import { prisma } from '@/lib/prisma';
import { redis } from '@/lib/redis';
import { getRequestContext } from '@/lib/context';
import type { Post } from '@prisma/client';
/**
* 获取当前用户的帖子列表。
* 这是应用中获取该数据的唯一入口点。
*/
export async function getPostsForCurrentUser(): Promise<Post[]> {
const { userId } = getRequestContext();
const cacheKey = `user:${userId}:posts`;
// --- 缓存逻辑预留位置 ---
// if (redis) {
// try {
// const cachedData = await redis.get(cacheKey);
// if (cachedData) return JSON.parse(cachedData);
// } catch (e) { console.error('Redis读取错误:', e); }
// }
const posts = await prisma.post.findMany({
orderBy: { createdAt: 'desc' },
});
// --- 缓存写入预留位置 ---
// if (redis) {
// try {
// // 将数据存入缓存,设置 2 分钟过期
// await redis.set(cacheKey, JSON.stringify(posts), 'EX', 120);
// } catch (e) { console.error('Redis写入错误:', e); }
// }
return posts;
}
/**
* 为当前用户创建一篇新帖子。
* @param data - 帖子的标题和内容
*/
export async function createPostForCurrentUser(data: { title: string; content?: string }): Promise<Post> {
const { userId } = getRequestContext();
const newPost = await prisma.post.create({
data: {
...data,
authorId: userId,
},
});
// --- 缓存失效逻辑预留位置 ---
const cacheKey = `user:${userId}:posts`;
// if (redis) {
// try {
// // 当创建新帖子后,必须清除旧的列表缓存
// await redis.del(cacheKey);
// } catch (e) { console.error('Redis缓存失效错误:', e); }
// }
return newPost;
}
4.7 API 路由模板 (app/api/my-posts/route.ts)
// app/api/my-posts/route.ts
import { getPostsForCurrentUser, createPostForCurrentUser } from '@/services/postService';
import { NextResponse } from 'next/server';
// 获取帖子列表
export async function GET() {
try {
const posts = await getPostsForCurrentUser();
return NextResponse.json(posts);
} catch (error) {
console.error(error);
return NextResponse.json({ message: '获取帖子失败' }, { status: 500 });
}
}
// 创建新帖子
export async function POST(request: Request) {
try {
const body = await request.json();
if (!body.title) {
return NextResponse.json({ message: '标题不能为空' }, { status: 400 });
}
const newPost = await createPostForCurrentUser({ title: body.title, content: body.content });
return NextResponse.json(newPost, { status: 201 });
} catch (error) {
console.error(error);
return NextResponse.json({ message: '创建帖子失败' }, { status: 500 });
}
}
5. 架构优势与开发策略
- 清晰的边界: 每个模块职责单一,API路由不含业务逻辑,服务层不含HTTP逻辑。
- 高度可维护: 当需要修改"获取帖子列表"的逻辑(例如增加一个字段或修改排序)时,你只需要修改
postService.ts一个文件。 - "即插即用"的性能: 当未来需要性能优化时,只需在
postService.ts中取消注释并实现缓存相关的代码即可,项目的任何其他部分都无需改动。这使得性能优化成为一个低风险、可预测的任务。 - 数据安全: 通过 PostgreSQL RLS 在数据库层面强制执行安全策略,确保即使代码有漏洞也不会泄露其他用户的数据。
6. 请求AI协助时的示例格式
当我向你请求代码时,我会尽量遵循以下格式,请根据这些信息进行响应:
- 目标 (Goal): (简要说明我想实现的功能)
- 上下文 (Context): (说明此功能所在的具体文件或组件路径)
- 数据模型 (Data Models): (指出需要参考的
prisma.schema中的模型) - 具体请求 (Request): (详细说明需要你生成的代码片段、函数或完整组件)
7. 版本控制与部署规范 (Version Control & Deployment)
7.1 Git 工作流规范
- 工具: Git
- 角色: 项目代码的版本管理工具。
- 规范:
- 所有代码变更都必须通过 Git 进行提交。
- 遵循 Conventional Commits 规范编写提交信息,便于追溯和自动化处理。
- 使用
.gitignore文件忽略不需要版本控制的文件和目录。
7.2 分支管理策略
- 主分支 (main/master):
- 始终保持稳定可部署状态
- 只接受来自
develop分支的合并请求 - 直接推送到主分支被严格禁止
- 开发分支 (develop):
- 集成分支,用于功能分支的合并
- 定期合并到主分支进行发布
- 功能分支 (feature/xxx):
- 重要: 所有新功能开发必须创建独立的功能分支
- 命名规范:
feature/功能描述或feature/issue-编号 - 从
develop分支创建,完成后合并回develop
7.3 SSH 公钥管理
- GitHub 公钥配置:
# 生成 SSH 密钥对 ssh-keygen -t ed25519 -C "your-email@example.com" # 添加到 SSH agent ssh-add ~/.ssh/id_ed25519 # 复制公钥到 GitHub cat ~/.ssh/id_ed25519.pub - 服务器公钥配置:
# 将开发者公钥添加到服务器 cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys chmod 700 ~/.ssh
7.4 CI/CD 流程与代码质量检查
🚀 目标: 建立完整的持续集成和持续部署流程,确保代码质量和部署安全性
🔒 质量门禁: 所有检查必须通过才能部署到生产环境
7.4.1 CI/CD 管道设计原则
- 质量门禁: 每个阶段都必须通过质量检查才能进入下一阶段
- 快速反馈: 尽早发现问题,减少修复成本
- 自动化优先: 减少人工干预,提高部署效率和一致性
7.4.2 GitHub Actions CI/CD 配置
创建 .github/workflows/ci-cd.yml 文件:
name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
# 代码质量检查阶段
quality-check:
runs-on: ubuntu-latest
name: 代码质量检查
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: 安装依赖
run: npm ci
- name: TypeScript 类型检查
run: npx tsc --noEmit
- name: ESLint 代码规范检查
run: npm run lint
- name: 构建检查
run: npm run build
- name: 运行测试 (可选)
run: npm run test
if: hashFiles('jest.config.*') != ''
# 安全扫描阶段
security-scan:
runs-on: ubuntu-latest
name: 安全扫描
needs: quality-check
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: 安装依赖
run: npm ci
- name: 依赖安全扫描
run: npm audit --audit-level=high
- name: 代码安全扫描
uses: github/codeql-action/analyze@v2
with:
languages: typescript
# 部署阶段(仅主分支)
deploy:
runs-on: ubuntu-latest
name: 部署到生产环境
needs: [quality-check, security-scan]
if: github.ref == 'refs/heads/main'
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 部署到服务器
uses: appleboy/ssh-action@v0.1.5
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /path/to/your/app
git pull origin main
npm ci --production
npm run build
pm2 restart app-name
7.4.3 质量门禁规则
🚫 零容忍: 任何一项检查失败都将阻止代码合并
✅ 必须通过: 以下所有检查项目必须全部通过才能合并到主分支
强制性检查项目:
- TypeScript 类型检查:
npx tsc --noEmit - 代码规范检查:
npm run lint - 构建验证:
npm run build - 单元测试 (可选):
npm run test(如果存在测试配置) - 安全扫描:
npm audit - 代码覆盖率 (可选): 最低 80%(如果配置了测试)
7.4.4 分支保护规则
🛡️ 分支保护: 通过 GitHub 分支保护规则强制执行代码质量标准
🔒 主分支保护: 防止直接推送到主分支,确保所有代码都经过审查
在 GitHub 仓库设置中配置分支保护:
{
"required_status_checks": {
"strict": true,
"contexts": [
"代码质量检查",
"安全扫描"
]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"required_approving_review_count": 1,
"dismiss_stale_reviews": true
},
"restrictions": null
}
7.5 服务器部署规范
- 部署原则:
- 严禁在服务器上直接修改代码
- 服务器只负责代码拉取和应用部署
- 所有代码修改必须在本地完成并推送到仓库
- 部署流程:
# 1. 服务器拉取最新代码 git pull origin main # 2. 安装/更新依赖 npm install --production # 3. 构建应用 npm run build # 4. 重启服务 pm2 restart app-name - 自动化部署脚本示例:
#!/bin/bash # deploy.sh echo "开始部署..." # 拉取最新代码 git pull origin main if [ $? -ne 0 ]; then echo "代码拉取失败" exit 1 fi # 安装依赖 npm install --production if [ $? -ne 0 ]; then echo "依赖安装失败" exit 1 fi # 构建应用 npm run build if [ $? -ne 0 ]; then echo "应用构建失败" exit 1 fi # 重启服务 pm2 restart app-name echo "部署完成"
7.5 .gitignore 文件内容
- 目的: 确保本地环境变量、依赖目录、构建产物和系统/IDE临时文件不会被提交到代码仓库。
# Dependencies /node_modules /.pnpm-store # Local Environment Variables (IMPORTANT!) .env .env.local .env.development.local .env.test.local .env.production.local # Next.js build output /.next/ /out/ # Production /build # Logs npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* # Editor directories and files .vscode/ .idea/ *.suo *.ntvs* *.njsproj *.sln *.sw? # macOS specific files .DS_Store # Deployment scripts (if containing sensitive info) deploy-config.sh
8. 环境配置与脚本规范
8.1 package.json 脚本配置
📦 配置说明: 完整的 npm 脚本配置,包含开发、构建、质量检查等所有必要脚本
🔧 可选脚本: 标记为"可选"的脚本可根据项目需求选择性配置
项目的 package.json 必须包含以下标准化脚本,支持不同环境的端口配置:
{
"scripts": {
"dev": "cross-env NODE_ENV=development PORT=3000 next dev",
"build": "next build",
"start": "cross-env NODE_ENV=production PORT=8080 next start",
"start:dev": "cross-env NODE_ENV=development PORT=3000 next start",
"start:prod": "cross-env NODE_ENV=production PORT=8080 next start",
"lint": "next lint",
"lint:fix": "next lint --fix",
"type-check": "tsc --noEmit",
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev",
"db:migrate:prod": "prisma migrate deploy",
"db:studio": "prisma studio",
"db:seed": "tsx prisma/seed.ts",
"test": "jest", // 🔧 可选:单元测试
"test:watch": "jest --watch", // 🔧 可选:监听模式测试
"test:coverage": "jest --coverage" // 🔧 可选:测试覆盖率
}
}
8.2 环境变量配置
- 开发环境 (
.env.local):NODE_ENV=development PORT=3000 DATABASE_URL="postgresql://user:password@localhost:5432/myapp_dev" NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET=your-dev-secret - 生产环境 (
.env.production):NODE_ENV=production PORT=8080 DATABASE_URL="postgresql://user:password@prod-server:5432/myapp_prod" NEXTAUTH_URL=https://yourdomain.com NEXTAUTH_SECRET=your-production-secret
8.3 端口配置规范
- 开发环境端口:
3000(默认 Next.js 开发端口) - 生产环境端口:
8080(避免与系统服务冲突) - 数据库端口:
5432(PostgreSQL 默认端口) - Redis 端口:
6379(Redis 默认端口,如果使用)
8.4 跨平台兼容性
- 使用
cross-env包确保环境变量在 Windows、macOS 和 Linux 上的兼容性 - PowerShell 兼容的脚本示例:
# 开发环境启动 $env:NODE_ENV="development"; $env:PORT="3000"; npm run dev # 生产环境启动 $env:NODE_ENV="production"; $env:PORT="8080"; npm run start
9. 代码质量检查与验证规范
9.1 TypeScript 类型检查规范
重要原则: AI写完代码后,必须进行类型检查和语法检查,确保没有错误后才能部署到线上。
- 类型检查命令:
# 类型检查(不生成文件,仅检查类型) npx tsc --noEmit # 或使用 npm script npm run type-check - 构建验证命令:
# 完整构建检查 npm run build # 或者分步检查 npm run lint # 代码规范检查 npm run type-check # 类型检查 npm run build # 构建检查 - TypeScript 配置要求 (
tsconfig.json):{ "compilerOptions": { "strict": true, // 启用严格模式 "noImplicitAny": true, // 禁止隐式 any "strictNullChecks": true, // 严格空值检查 "noImplicitReturns": true, // 函数必须有返回值 "noUnusedLocals": true, // 🔧 可选:检查未使用的局部变量 "noUnusedParameters": true, // 🔧 可选:检查未使用的参数 "exactOptionalPropertyTypes": true // 🔧 可选:精确可选属性类型 } }
9.2 代码质量检查流程
🎯 目标: 建立严格的代码质量保障体系,确保代码质量和项目稳定性
⚡ 执行时机: 每次提交前、构建前、部署前
强制性检查步骤 - AI 完成代码编写后必须执行:
-
第一步:类型检查
npx tsc --noEmit- 必须确保没有任何 TypeScript 类型错误
- 严禁使用
any类型,必须明确定义所有类型 - 如有类型错误,必须立即修复后再进行下一步
-
第二步:代码规范检查
npm run lint- 检查代码风格和潜在问题
- 自动修复可修复的问题:
npm run lint:fix
-
第三步:构建验证
npm run build- 验证代码能够成功构建
- 检查是否有运行时可能出现的问题
- 确保所有依赖和导入正确
-
第四步:测试验证 (可选)
npm run test # 🔧 仅在项目配置了测试时执行- 仅在项目包含测试配置文件时执行
- 如无测试配置,可跳过此步骤
9.3 错误处理与修复规范
- 类型错误修复:
- 为所有函数参数和返回值添加明确的类型注解
- 使用 TypeScript 的联合类型、交叉类型等高级特性
- 避免使用
any,改用unknown或具体类型
- 构建错误修复:
- 检查所有 import/export 语句
- 确保所有依赖包已正确安装
- 验证环境变量和配置文件
- 示例:正确的类型定义
// ❌ 错误:使用 any function processData(data: any): any { return data.someProperty; } // ✅ 正确:明确类型定义 interface UserData { id: string; name: string; email: string; } function processUserData(data: UserData): string { return data.name; } // ✅ 正确:使用泛型 function processApiResponse<T>(response: { data: T; status: number }): T { return response.data; }
9.4 预提交检查规范
部署前必检项目:
# 完整的预提交检查脚本
#!/bin/bash
echo "🔍 开始代码质量检查..."
# 1. TypeScript 类型检查
echo "📝 执行 TypeScript 类型检查..."
npx tsc --noEmit
if [ $? -ne 0 ]; then
echo "❌ TypeScript 类型检查失败,请修复类型错误"
exit 1
fi
echo "✅ TypeScript 类型检查通过"
# 2. ESLint 检查
echo "🔧 执行代码规范检查..."
npm run lint
if [ $? -ne 0 ]; then
echo "❌ 代码规范检查失败,请修复代码规范问题"
exit 1
fi
echo "✅ 代码规范检查通过"
# 3. 构建检查
echo "🏗️ 执行构建检查..."
npm run build
if [ $? -ne 0 ]; then
echo "❌ 构建失败,请检查代码和依赖"
exit 1
fi
echo "✅ 构建检查通过"
# 4. 测试检查(可选 - 仅在配置了测试时执行)
if [ -f "jest.config.js" ] || [ -f "jest.config.ts" ]; then
echo "🧪 执行测试..."
npm run test
if [ $? -ne 0 ]; then
echo "❌ 测试失败,请修复测试问题"
exit 1
fi
echo "✅ 测试通过"
else
echo "ℹ️ 未检测到测试配置,跳过测试步骤"
fi
echo "🎉 所有检查通过,代码可以部署!"
9.5 PowerShell 版本检查脚本
针对 Windows PowerShell 环境的检查脚本:
# pre-deploy-check.ps1
Write-Host "🔍 开始代码质量检查..." -ForegroundColor Blue
# 1. TypeScript 类型检查
Write-Host "📝 执行 TypeScript 类型检查..." -ForegroundColor Yellow
npx tsc --noEmit
if ($LASTEXITCODE -ne 0) {
Write-Host "❌ TypeScript 类型检查失败,请修复类型错误" -ForegroundColor Red
exit 1
}
Write-Host "✅ TypeScript 类型检查通过" -ForegroundColor Green
# 2. ESLint 检查
Write-Host "🔧 执行代码规范检查..." -ForegroundColor Yellow
npm run lint
if ($LASTEXITCODE -ne 0) {
Write-Host "❌ 代码规范检查失败,请修复代码规范问题" -ForegroundColor Red
exit 1
}
Write-Host "✅ 代码规范检查通过" -ForegroundColor Green
# 3. 构建检查
Write-Host "🏗️ 执行构建检查..." -ForegroundColor Yellow
npm run build
if ($LASTEXITCODE -ne 0) {
Write-Host "❌ 构建失败,请检查代码和依赖" -ForegroundColor Red
exit 1
}
Write-Host "✅ 构建检查通过" -ForegroundColor Green
# 4. 测试检查(可选 - 仅在配置了测试时执行)
if (Test-Path "jest.config.js" -Or Test-Path "jest.config.ts") {
Write-Host "🧪 执行测试..." -ForegroundColor Yellow
npm run test
if ($LASTEXITCODE -ne 0) {
Write-Host "❌ 测试失败,请修复测试问题" -ForegroundColor Red
exit 1
}
Write-Host "✅ 测试通过" -ForegroundColor Green
} else {
Write-Host "ℹ️ 未检测到测试配置,跳过测试步骤" -ForegroundColor Cyan
}
Write-Host "🎉 所有检查通过,代码可以部署!" -ForegroundColor Green
9.6 开发调试规范
写代码的时候要及时预留关键变量打印,方便调试。在服务层函数中适当添加 console.log 来跟踪数据流和业务逻辑执行情况。
10. 错误处理与文档维护规范
9.1 错误处理流程
- 错误发现: 在开发、测试或生产环境中发现错误时,应立即记录错误详情。
- 错误修复: 修复错误后,必须进行充分测试确保问题解决。
- 文档同步: 重要: 错误修复后,必须及时让AI将修复后的代码和相关文档导入到
/docs目录中,确保文档与代码保持同步。
9.2 文档维护规范
- 文档结构:
/docs/ ├── api/ # API 文档 ├── architecture/ # 架构设计文档 ├── deployment/ # 部署相关文档 ├── troubleshooting/ # 故障排除指南 └── changelog/ # 变更日志 - 文档更新触发条件:
- 修复重要错误后
- 添加新功能后
- 修改架构设计后
- 更新部署流程后
- 文档内容要求:
- 包含错误描述、原因分析、解决方案
- 提供代码示例和配置说明
- 记录相关的环境变量和依赖变更
- 更新相关的API文档和使用说明
9.3 错误日志规范
- 日志级别: 使用标准日志级别 (ERROR, WARN, INFO, DEBUG)
- 错误上下文: 记录足够的上下文信息便于问题定位
- 敏感信息: 严禁在日志中记录密码、密钥等敏感信息
// 错误处理示例
try {
const result = await someOperation();
console.info('操作成功完成', { userId, operationType: 'create_post' });
return result;
} catch (error) {
console.error('操作失败', {
userId,
operationType: 'create_post',
error: error.message,
stack: error.stack
});
throw new Error('创建帖子失败,请稍后重试');
}
11. 完整项目生命周期管理
11.1 项目初始化阶段
- 环境准备:
# 1. 创建项目 npx create-next-app@latest project-name --typescript --tailwind --eslint --app # 2. 安装核心依赖 npm install prisma @prisma/client next-auth @auth/prisma-adapter npm install @vercel/ai ai openai npm install @aws-sdk/client-s3 npm install ioredis npm install cross-env # 3. 安装开发依赖 (可选) npm install -D tsx jest @types/jest # 🔧 可选:测试相关依赖 - 项目结构初始化:
# 创建必要目录 mkdir -p src/services src/lib prisma docs mkdir -p docs/{api,architecture,deployment,troubleshooting,changelog} - 配置文件设置:
- 配置
prisma/schema.prisma - 设置
.env.local和.env.example - 配置
middleware.ts - 设置
tailwind.config.js和next.config.js
- 配置
11.2 开发阶段
- 功能开发流程:
- 创建功能分支:
git checkout -b feature/new-feature - 数据库模型设计: 修改
prisma/schema.prisma - 生成 Prisma 客户端:
npm run db:generate - 创建数据库迁移:
npm run db:migrate - 实现服务层逻辑: 在
src/services/中创建业务服务 - 实现 API 路由: 在
src/app/api/中创建接口 - 实现前端组件: 在
src/components/和src/app/中创建页面 - 编写测试: 在
__tests__/目录中添加测试用例
- 创建功能分支:
- 代码质量检查:
# 类型检查 npm run type-check # 代码规范检查 npm run lint # 自动修复代码规范问题 npm run lint:fix # 运行测试 npm run test
11.3 测试阶段 (可选)
🔧 可选阶段 - 根据项目规模和质量要求决定是否实施完整的测试流程。
- 测试类型:
- 单元测试: 测试服务层函数和工具函数
- 集成测试: 测试 API 路由和数据库交互
- 端到端测试: 测试完整的用户流程
- 测试环境配置:
# .env.test NODE_ENV=test DATABASE_URL="postgresql://user:password@localhost:5432/myapp_test" - 测试数据管理:
// prisma/seed.ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function main() { // 创建测试数据 await prisma.user.createMany({ data: [ { email: 'test1@example.com', name: 'Test User 1' }, { email: 'test2@example.com', name: 'Test User 2' }, ], }); } main() .catch((e) => console.error(e)) .finally(async () => await prisma.$disconnect());
11.4 构建与部署阶段
- 构建前检查:
# 1. 确保所有测试通过 (可选) npm run test # 🔧 仅在配置了测试时执行 # 2. 类型检查 npm run type-check # 3. 代码规范检查 npm run lint # 4. 构建应用 npm run build - 部署前准备:
- 确保生产环境变量配置正确
- 运行生产数据库迁移:
npm run db:migrate:prod - 验证所有外部服务连接 (数据库、Redis、OSS)
- 部署流程:
- 合并代码到主分支
- 服务器拉取最新代码
- 安装生产依赖
- 构建应用
- 运行数据库迁移
- 重启服务
11.5 监控与维护阶段
- 性能监控 (可选):
- 应用性能监控 (APM) 🔧 可选
- 数据库性能监控 🔧 可选
- 服务器资源监控
- 用户体验监控 🔧 可选
- 日志管理:
// lib/logger.ts export const logger = { info: (message: string, meta?: object) => { console.log(JSON.stringify({ level: 'info', message, meta, timestamp: new Date().toISOString() })); }, error: (message: string, error?: Error, meta?: object) => { console.error(JSON.stringify({ level: 'error', message, error: error?.message, stack: error?.stack, meta, timestamp: new Date().toISOString() })); }, }; - 备份策略:
- 数据库定期备份
- 代码仓库备份
- 配置文件备份
- 静态资源备份
11.6 安全管理
- 安全检查清单:
- 环境变量安全 (不提交敏感信息到代码仓库)
- 数据库连接安全 (使用 SSL)
- API 接口安全 (认证和授权)
- 文件上传安全 (类型和大小限制)
- XSS 和 CSRF 防护
- 依赖包安全扫描
- 定期安全维护:
# 检查依赖包漏洞 npm audit # 修复已知漏洞 npm audit fix # 更新依赖包 npm update
11.7 文档维护
- 文档更新触发点:
- 新功能发布
- API 接口变更
- 部署流程变更
- 安全策略更新
- 重大 Bug 修复
- 文档类型:
- API 文档 (自动生成 + 手动维护)
- 架构设计文档
- 部署运维文档
- 故障排除指南
- 变更日志
11.8 版本发布管理
- 版本号规范: 遵循 语义化版本 (Semantic Versioning)
MAJOR.MINOR.PATCH(主版本.次版本.修订版本)- 主版本: 不兼容的 API 修改
- 次版本: 向下兼容的功能性新增
- 修订版本: 向下兼容的问题修正
- 发布流程:
- 创建发布分支:
git checkout -b release/v1.2.0 - 更新版本号: 修改
package.json中的 version - 更新 CHANGELOG.md
- 合并到主分支并打标签:
git tag v1.2.0 - 部署到生产环境
- 发布公告和文档更新
- 创建发布分支: