Eyre
Eyre
发布于 2025-10-09 / 23 阅读
0
0

项目技术栈与开发规范

项目技术栈与开发规范

📋 目录导航

1. 核心技术栈

📌 重要说明: 以下是我们项目使用的核心技术栈。所有代码生成和技术方案都必须严格遵守此规范。

🔧 可选组件说明: 标记为"可选"的组件可根据项目需求和开发阶段灵活选择是否启用。

以下是我们项目使用的核心技术栈:

  • 应用框架: Next.js 15+
    • 角色: 全栈Web框架。
    • 规范:
      • 路由: 严格使用 App Router (/src/app 目录结构)。
      • 组件: 默认使用 React Server Components (RSC) 进行数据获取和后端逻辑处理。仅在需要交互性时(如 onClick, useState)使用 'use client' 声明客户端组件。
      • 数据交互: 优先使用 Server Actions 处理表单提交和数据变更 (Mutations)。
  • 认证: NextAuth.js
    • 角色: 处理用户认证和会话管理。
    • 规范: 与中间件集成,提供用户身份信息给安全架构使用。
  • UI & 样式:
    • 组件库: shadcn/ui
    • CSS框架: Tailwind CSS
      • 角色: 用于所有样式定义。
      • 规范: 采用原子化CSS类进行样式编写。避免使用原生CSS文件,除非用于全局基础样式定义 (/src/app/globals.css)。
  • AI 核心: Vercel AI SDK
    • 角色: 连接前端与大型语言模型 (LLM) API的桥梁。
    • 规范:
      • 使用其提供的React Hooks (如 useChat, useCompletion) 在客户端组件中实现流式响应。
      • 在Server Actions或Route Handlers中调用其核心函数,与AI模型进行交互。
  • 数据库: PostgreSQL (with pgvector extension)
    • 角色: 主数据库,用于存储结构化数据和向量数据。
    • 规范: 必须启用并使用 pgvector 扩展来支持向量的存储和相似度搜索。
    • 安全: 启用行级安全 (Row-Level Security, RLS) 确保数据访问权限在数据库层面强制执行。
  • ORM: Prisma
    • 角色: 数据库访问层,提供类型安全的数据库操作。便于拓展。
    • 规范:
      • 模型定义: 唯一的真实数据源是 /prisma/schema.prisma 文件。所有数据模型必须在此文件中定义。
      • 工作流:
        1. 修改 schema.prisma 文件。
        2. 本地开发运行 npx prisma generate 来更新Prisma Client类型。
        3. 本地开发运行 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,不存储文件本身。

2. 安全架构设计原则

2.1 目标与愿景

本项目采用一种在现代Web应用中实现健壮、可维护、高性能且对开发者友好的数据架构方案。其核心目标是:

  • 极致安全: 数据访问权限在数据库层面强制执行(RLS),确保用户只能访问其自身拥有的数据。
  • 关注点分离:
    • API路由/页面 负责处理HTTP请求与响应。
    • 服务层 负责封装和集中化所有业务逻辑与数据访问策略。
    • 数据层 (Prisma/PostgreSQL) 负责数据的持久化与安全过滤。
  • 性能就绪 (Performance-Ready): 架构从第一天起就为引入缓存(如 Redis)预留了位置,未来可无缝激活性能优化,而无需重构。
  • 卓越的开发体验 (DX): 业务代码简洁、直观,无需关心底层的RLS实现或数据来源(数据库/缓存)。

2.2 请求生命周期

一个受保护的请求从发起到响应的完整流程如下:

  1. [请求入口] Next.js Middleware:
    • 拦截请求,解析用户身份 (userId)。
    • userId 注入到 AsyncLocalStorage 上下文中,供后续调用链使用。
  2. [调用层] API 路由 / Server Component:
    • 职责非常单一:处理HTTP层的事务(解析请求体、返回JSON响应等)。
    • 它不再直接与 prisma 交互,而是调用服务层中定义好的函数来完成业务需求。例如 await postService.getPostsForCurrentUser()
  3. [服务层] 数据服务 / 业务逻辑封装:
    • 架构的核心。所有业务逻辑和数据访问被封装在此处(例如 services/postService.ts)。
    • 它是数据来源的决策者。这里是为Redis预留的位置。它会决定是从缓存(未来)还是从数据库获取数据。
    • 它调用 prisma 客户端来执行数据库操作。
  4. [数据访问层] Prisma Client Extension:
    • 服务层调用 prisma 时,增强的Client Extension会被触发。
    • 它从 AsyncLocalStorage 中读取 userId,并通过事务安全地设置PostgreSQL的会话变量 app.current_user_id
  5. [数据库层] PostgreSQL RLS 执行:
    • PostgreSQL 根据会话变量和预设的RLS策略,在底层完成数据过滤。
  6. [响应] 返回安全数据:
    • 安全的数据沿调用链原路返回: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 质量门禁规则

🚫 零容忍: 任何一项检查失败都将阻止代码合并

必须通过: 以下所有检查项目必须全部通过才能合并到主分支

强制性检查项目

  1. TypeScript 类型检查: npx tsc --noEmit
  2. 代码规范检查: npm run lint
  3. 构建验证: npm run build
  4. 单元测试 (可选): npm run test(如果存在测试配置)
  5. 安全扫描: npm audit
  6. 代码覆盖率 (可选): 最低 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 完成代码编写后必须执行:

  1. 第一步:类型检查

    npx tsc --noEmit
    
    • 必须确保没有任何 TypeScript 类型错误
    • 严禁使用 any 类型,必须明确定义所有类型
    • 如有类型错误,必须立即修复后再进行下一步
  2. 第二步:代码规范检查

    npm run lint
    
    • 检查代码风格和潜在问题
    • 自动修复可修复的问题:npm run lint:fix
  3. 第三步:构建验证

    npm run build
    
    • 验证代码能够成功构建
    • 检查是否有运行时可能出现的问题
    • 确保所有依赖和导入正确
  4. 第四步:测试验证 (可选)

    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.jsnext.config.js

11.2 开发阶段

  • 功能开发流程:
    1. 创建功能分支: git checkout -b feature/new-feature
    2. 数据库模型设计: 修改 prisma/schema.prisma
    3. 生成 Prisma 客户端: npm run db:generate
    4. 创建数据库迁移: npm run db:migrate
    5. 实现服务层逻辑: 在 src/services/ 中创建业务服务
    6. 实现 API 路由: 在 src/app/api/ 中创建接口
    7. 实现前端组件: 在 src/components/src/app/ 中创建页面
    8. 编写测试: 在 __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)
  • 部署流程:
    1. 合并代码到主分支
    2. 服务器拉取最新代码
    3. 安装生产依赖
    4. 构建应用
    5. 运行数据库迁移
    6. 重启服务

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 修改
    • 次版本: 向下兼容的功能性新增
    • 修订版本: 向下兼容的问题修正
  • 发布流程:
    1. 创建发布分支: git checkout -b release/v1.2.0
    2. 更新版本号: 修改 package.json 中的 version
    3. 更新 CHANGELOG.md
    4. 合并到主分支并打标签: git tag v1.2.0
    5. 部署到生产环境
    6. 发布公告和文档更新

评论