frontend-technical-spec · git:20260923.03f66be · 2026-09-23 · sha256 8811d125a473087d
frontend-technical-spec git:20260923.03f66beA
Immutable. This exact content never changes and is served at /api/v1/blob/8811d125a473087d.
---
name: frontend-technical-spec
description: 根据仓库依据定义 React 环境、组件架构、状态/数据流、构建验证以及前端非功能性标准。用于配置或设计 React 前端及其构建、运行时边界时使用。
---
# 技术设计规则(前端)
## 前置条件检测
在应用工具或框架相关规则之前,先检查 `package.json`、锁文件、TypeScript/构建配置、CI 定义以及具有代表性的组件。只有当仓库依据明确指出时,才可将 React、Vite、Next.js、状态库、表单库或脚本视为可用。将基于周边模式得出的结论标注为推断结果。当某个缺失的决策会影响渲染架构、兼容性、安全性或验证方式时,停下来并指出所需的具体依据或用户决策。
## 基础技术栈方针
以下规则适用于仓库配置已确认为基于 TypeScript 的 React 应用的情况。通过将当前需求与约束映射到组件职责、状态归属、服务端/客户端边界以及可观测的验证点来选择架构。
## 环境变量管理与安全
### 环境变量管理
- **使用构建工具的客户端暴露机制**:浏览器代码只能读取由所配置的打包工具/框架明确暴露的值;仅服务端可访问的环境变量不会进入客户端包
- 通过配置层集中管理环境变量
- 在应用使用前,在一个类型化的配置边界处解析所有暴露的值
- 仅当需求中定义了值缺失时的有效行为时才为其设置默认值;否则应在启动/构建验证阶段失败,并给出变量名和期望格式
```typescript
// 构建工具环境变量(仅限公开值;客户端暴露的变量需要 VITE_ 前缀)
const config = {
apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3000',
appName: import.meta.env.VITE_APP_NAME || 'My App'
}
// 在前端中不可用
const apiUrl = process.env.API_URL
```
### 安全性(客户端约束)
- **关键**:所有前端代码都是公开的,在浏览器中可见
- **将机密信息保留在服务端**:客户端暴露的配置只应包含公开值;API 密钥、令牌和凭据应由后端或受信任的服务持有
- 将本地 `.env` 文件排除在版本控制之外,并为所需的变量名提供不含机密信息的示例文件
- 只记录和返回当前信任边界所批准的字段;对密码、令牌和个人数据进行脱敏
**处理机密信息的正确方式**:
```typescript
// 安全风险:API 密钥在浏览器中暴露
const apiKey = import.meta.env.VITE_API_KEY
const response = await fetch(`https://api.example.com/data?key=${apiKey}`)
// 正确做法:后端管理机密信息,前端通过代理访问
const response = await fetch('/api/data') // 后端负责处理 API 密钥认证
```
## 架构设计
### 前端架构模式
**React 组件架构**:
- **函数组件**:强制要求;仅在 Error Boundary 场景下允许使用类组件(因为没有对应的 hook 替代方案)
- **自定义 Hook**:用于逻辑复用和依赖注入
- **组件层级**:Atoms -> Molecules -> Organisms -> Templates -> Pages
- **Props 驱动**:组件通过 props 接收所有必要数据
- **就近放置**:将测试、样式和相关文件放在组件旁边
按以下规则选择组件/状态模式:
- 当某个组件子树独占所有读写权限时,保持状态为局部状态
- 当多个后代组件需要相同的低频状态且 provider 边界明确时,使用 Context
- 仅当已配置该依赖项存在,且需要缓存、去重、后台刷新或请求生命周期状态时,才使用服务端状态库
- 仅当当前需求无法用局部状态、reducer 状态、已有 Context 或仓库既有的状态管理机制覆盖时,才引入新的状态管理依赖
**状态管理模式**:
- **局部状态**:使用 `useState` 管理组件专属状态
- **Context API**:用于跨组件树共享状态(主题、认证等)
- **自定义 Hook**:封装状态逻辑和副作用
- **服务端状态**:使用 React Query 或 SWR 缓存 API 数据
## 统一数据流原则
### 客户端数据流
在整个 React 应用中保持一致的数据流:
- **单一数据源**:每一份状态只有一个权威来源
- UI 状态:组件状态或 Context
- 服务端数据:缓存在 React Query/SWR 中的 API 响应
- 表单数据:使用 React Hook Form 的受控组件
- **单向流动**:数据通过 props 自上而下流动
```
API Response -> State -> Props -> Render -> UI
User Input -> Event Handler -> State Update -> Re-render
```
- **不可变更新**:状态更新时使用不可变模式
```typescript
// 不可变的状态更新
setUsers(prev => [...prev, newUser])
// 无效的可变状态更新
users.push(newUser)
setUsers(users)
```
### 数据流中的类型安全
- **前端 -> 后端**:Props/State(类型有保证)-> API 请求(序列化)
- **后端 -> 前端**:API 响应(`unknown`)-> 类型守卫 -> State(类型有保证)
```typescript
// 类型安全的数据流
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`)
const data: unknown = await response.json()
if (!isUser(data)) {
throw new Error('Invalid user data')
}
return data // 类型已保证为 User
}
```
## 构建与测试
按以下优先级从 `packageManager` 字段、锁文件或 CI 命令中确定包管理器。只执行所选清单文件中存在的脚本。
### 构建命令
- 从 package.json 的 scripts 中自动检测并执行以下内容:
- 开发服务器
- 生产构建
- 类型检查(不生成输出)
### 测试命令
- `test` - 运行测试
### 质量检查要求
实现完成后必须进行质量检查:
**阶段 1-3:基础检查**
- `check` - Biome(lint + format)
- `build` - TypeScript 构建
**阶段过渡依据**:所有已配置的 lint/format/type/build 检查均成功退出。缺失的必需脚本应连同其清单/配置路径一并报告,其余检查仍照常运行;该缺失的检查是否导致所需证明不可得,由 quality-fixer 的结果判定。
**阶段 4-5:测试与最终确认**
- `test` - 执行测试
- `check:all` - 整体集成检查
**完成依据**:已配置的测试全部通过,生产构建成功,且在测试修复后整体集成检查仍保持通过。将依赖特定环境的测试记录为受阻状态,并注明其确切的前提条件。
### 测试重点
- 对共享组件、自定义 Hook、工具函数等基础的、高复用性的单元,针对其可观测契约直接编写测试。对于 organisms、pages 等更高组合层级的界面,当该边界最能暴露相关故障时,通过集成测试或 E2E 测试进行验证
### 非功能需求
- **浏览器兼容性**:使用仓库中的 Browserslist/构建目标,或明确指定的产品需求;记录来源,并测试受影响的浏览器特定行为
- **渲染性能**:使用项目需求、CI 或性能配置中定义的浏览器矩阵和性能阈值。如果不存在,则将测得的情况作为诊断性依据报告,而不臆造通过阈值