团队协作规范
团队协作规范的重要性
TypeScript项目的团队协作规范是保证代码质量、提升开发效率的关键因素。缺乏统一规范的团队往往会陷入代码风格混乱、功能冲突、维护成本高的困境。明确的协作规范能减少沟通成本,让开发者专注于业务逻辑实现而非格式争议。
代码风格统一
使用ESLint和Prettier工具强制统一代码风格。配置应该包含在项目根目录下,确保所有成员使用相同规则。
// .eslintrc.js 示例配置
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'no-console': 'warn'
}
};
类型系统规范
TypeScript的核心优势在于类型系统,团队应该制定明确的类型使用规范:
- 避免使用
any
类型,必要时使用unknown
代替 - 为公共API编写详细的类型注释
- 使用类型别名和接口组织复杂类型
// 良好的类型定义示例
interface UserProfile {
id: string;
name: string;
email: string;
lastLogin?: Date;
}
type UserRole = 'admin' | 'editor' | 'viewer';
function getUserRoles(userId: string): Promise<UserRole[]> {
// 实现逻辑
}
分支管理策略
采用Git Flow或类似的分支管理策略:
main
分支保持可发布状态develop
分支作为集成分支- 功能分支从
develop
创建,命名格式为feature/功能名称
- 修复分支从
main
创建,命名格式为hotfix/问题描述
# 创建功能分支示例
git checkout -b feature/user-authentication develop
提交信息规范
使用约定式提交(Conventional Commits)规范:
<类型>[可选的作用域]: <描述>
[可选的正文]
[可选的脚注]
常见类型包括:
- feat: 新功能
- fix: bug修复
- docs: 文档变更
- style: 代码格式变更
- refactor: 代码重构
- test: 测试相关变更
- chore: 构建过程或辅助工具的变更
代码审查标准
建立明确的代码审查清单:
- 功能实现是否符合需求
- 是否包含适当的单元测试
- 代码是否遵循项目类型规范
- 是否有明显的性能问题
- 错误处理是否完备
- 文档是否同步更新
模块化设计原则
遵循SOLID原则设计模块:
// 良好的模块化示例
abstract class PaymentProcessor {
abstract processPayment(amount: number): Promise<PaymentResult>;
}
class CreditCardProcessor extends PaymentProcessor {
async processPayment(amount: number): Promise<PaymentResult> {
// 信用卡支付实现
}
}
class PayPalProcessor extends PaymentProcessor {
async processPayment(amount: number): Promise<PaymentResult> {
// PayPal支付实现
}
}
测试规范
测试应该覆盖核心业务逻辑:
- 单元测试覆盖率不低于80%
- 为每个公共方法编写测试用例
- 使用描述性的测试名称
// 测试示例
describe('UserService', () => {
let userService: UserService;
let mockUserRepository: jest.Mocked<UserRepository>;
beforeEach(() => {
mockUserRepository = {
findById: jest.fn(),
save: jest.fn()
};
userService = new UserService(mockUserRepository);
});
test('should return user when found', async () => {
const mockUser = { id: '1', name: 'Test User' };
mockUserRepository.findById.mockResolvedValue(mockUser);
const result = await userService.getUser('1');
expect(result).toEqual(mockUser);
});
});
文档规范
保持文档与代码同步更新:
- 为每个模块编写README.md
- 使用TypeDoc生成API文档
- 记录重要的设计决策
/**
* 用户服务类,提供用户相关操作
* @class
*/
class UserService {
/**
* 根据ID获取用户
* @param userId - 用户唯一标识
* @returns 用户对象或null
*/
async getUser(userId: string): Promise<User | null> {
// 实现逻辑
}
}
持续集成流程
配置CI/CD流水线自动执行:
- 代码风格检查
- 类型检查
- 单元测试
- 构建验证
# GitHub Actions 示例
name: CI Pipeline
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm ci
- run: npm run lint
- run: npm run test
- run: npm run build
依赖管理策略
保持依赖项更新和安全:
- 定期运行
npm outdated
检查过时依赖 - 使用
npm audit
检查安全漏洞 - 锁定依赖版本号
// package.json 示例片段
{
"dependencies": {
"react": "18.2.0",
"typescript": "~4.7.4"
},
"devDependencies": {
"@types/react": "^18.0.15",
"eslint": "8.23.0"
}
}
错误处理约定
统一错误处理方式:
- 使用自定义错误类
- 在类型中明确可能抛出的错误
- 提供有意义的错误信息
class AppError extends Error {
constructor(
public readonly code: string,
message: string,
public readonly details?: unknown
) {
super(message);
this.name = 'AppError';
}
}
async function fetchData(url: string): Promise<Data> {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
throw new AppError(
'FETCH_FAILED',
`Failed to fetch data from ${url}`,
{ originalError: error }
);
}
}
性能优化指南
制定性能优化标准:
- 避免在渲染循环中进行复杂计算
- 使用适当的数据结构
- 减少不必要的重新渲染
// 性能优化示例
function ExpensiveComponent({ items }: { items: Item[] }) {
const processedItems = useMemo(() => {
return items.map(processItem);
}, [items]);
return <ItemList items={processedItems} />;
}
代码组织结构
保持一致的目录结构:
src/
├── components/ # 公共组件
├── hooks/ # 自定义Hook
├── services/ # 业务服务
├── stores/ # 状态管理
├── types/ # 全局类型定义
├── utils/ # 工具函数
└── pages/ # 页面组件
类型导出规范
合理组织类型导出:
- 在
types
目录集中管理全局类型 - 避免污染全局命名空间
- 使用命名空间组织相关类型
// types/user.d.ts
declare namespace User {
interface Profile {
id: string;
name: string;
}
type Role = 'admin' | 'user';
}
// 使用示例
const user: User.Profile = {
id: '123',
name: 'John Doe'
};
异步处理模式
统一异步代码风格:
- 优先使用async/await
- 为Promise添加类型注解
- 处理可能的拒绝情况
// 良好的异步处理示例
async function loadUserData(userId: string): Promise<UserData> {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json() as UserData;
} catch (error) {
console.error('Failed to load user data:', error);
throw error;
}
}
组件设计原则
React组件设计规范:
- 保持组件单一职责
- 合理划分容器组件和展示组件
- 使用Props类型定义组件接口
interface UserCardProps {
user: User;
onEdit?: (user: User) => void;
onDelete?: (userId: string) => void;
}
const UserCard: React.FC<UserCardProps> = ({ user, onEdit, onDelete }) => {
return (
<div className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
{onEdit && <button onClick={() => onEdit(user)}>Edit</button>}
{onDelete && <button onClick={() => onDelete(user.id)}>Delete</button>}
</div>
);
};
状态管理策略
根据项目复杂度选择状态管理方案:
- 小型项目使用React Context
- 中型项目使用Zustand或Jotai
- 大型复杂项目考虑Redux
// Zustand 示例
import create from 'zustand';
interface UserStore {
user: User | null;
setUser: (user: User) => void;
clearUser: () => void;
}
const useUserStore = create<UserStore>((set) => ({
user: null,
setUser: (user) => set({ user }),
clearUser: () => set({ user: null })
}));
// 组件中使用
function UserProfile() {
const user = useUserStore(state => state.user);
// ...
}
工具函数规范
工具函数应该:
- 保持纯函数特性
- 包含完整的类型定义
- 有明确的单测覆盖
// 工具函数示例
/**
* 格式化日期为YYYY-MM-DD格式
* @param date - 日期对象或可转换为日期的字符串
* @returns 格式化后的日期字符串
*/
function formatDate(date: Date | string): string {
const d = new Date(date);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
环境变量管理
安全地管理环境变量:
- 使用
.env
文件存储敏感信息 - 在代码中通过
process.env
访问 - 为环境变量创建类型定义
// env.d.ts
declare namespace NodeJS {
interface ProcessEnv {
readonly REACT_APP_API_URL: string;
readonly REACT_APP_ENV: 'development' | 'production';
}
}
// 使用示例
const apiUrl = process.env.REACT_APP_API_URL;
代码复用策略
提高代码复用性的方法:
- 提取公共自定义Hook
- 创建高阶组件
- 设计可组合的实用工具
// 自定义Hook示例
function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue] as const;
}
国际化支持
为多语言支持做好准备:
- 使用i18next等库
- 集中管理翻译资源
- 为翻译键名建立命名规范
// 国际化资源示例
const resources = {
en: {
translation: {
welcome: "Welcome",
userGreeting: "Hello, {{name}}!"
}
},
zh: {
translation: {
welcome: "欢迎",
userGreeting: "你好,{{name}}!"
}
}
};
// 组件中使用
function Greeting() {
const { t } = useTranslation();
return <h1>{t('welcome')}</h1>;
}
可访问性标准
确保应用可访问:
- 为交互元素添加ARIA属性
- 保证键盘导航可用
- 提供足够的颜色对比度
// 可访问的按钮组件
interface AccessibleButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
loading?: boolean;
}
const AccessibleButton: React.FC<AccessibleButtonProps> = ({
children,
loading,
...props
}) => {
return (
<button
{...props}
aria-busy={loading}
aria-disabled={loading || props.disabled}
>
{loading ? 'Loading...' : children}
</button>
);
};
响应式设计原则
实现响应式布局:
- 使用CSS媒体查询
- 采用移动优先策略
- 避免固定像素值
// 响应式Hook示例
function useMediaQuery(query: string): boolean {
const [matches, setMatches] = useState(false);
useEffect(() => {
const media = window.matchMedia(query);
if (media.matches !== matches) {
setMatches(media.matches);
}
const listener = () => setMatches(media.matches);
media.addListener(listener);
return () => media.removeListener(listener);
}, [matches, query]);
return matches;
}
// 使用示例
const isMobile = useMediaQuery('(max-width: 768px)');
版本兼容性策略
处理API版本兼容:
- 在请求头中指定API版本
- 为不同版本维护类型定义
- 提供版本迁移指南
// API客户端版本控制示例
class ApiClient {
private readonly baseUrl: string;
private readonly version: string;
constructor(baseUrl: string, version = 'v1') {
this.baseUrl = baseUrl;
this.version = version;
}
async get<T>(endpoint: string): Promise<T> {
const response = await fetch(`${this.baseUrl}/${this.version}${endpoint}`, {
headers: {
'Accept': `application/vnd.myapp.${this.version}+json`
}
});
return response.json();
}
}
代码分割方案
优化应用加载性能:
- 按路由分割代码
- 动态导入重型组件
- 预加载关键资源
// 动态导入示例
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<LoadingSpinner />}>
<HeavyComponent />
</Suspense>
);
}
数据获取模式
统一数据获取方式:
- 使用SWR或React Query管理服务端状态
- 实现请求取消功能
- 处理加载和错误状态
// React Query 示例
function UserList() {
const { data: users, isLoading, error } = useQuery<User[], Error>(
'users',
() => fetch('/api/users').then(res => res.json())
);
if (isLoading) return <Spinner />;
if (error) return <Error message={error.message} />;
return (
<ul>
{users?.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
样式管理方案
选择合适的样式方案:
- CSS Modules提供局部作用域
- Styled-components支持主题
- Utility-first框架如Tailwind提高开发效率
// CSS Modules 示例
import styles from './Button.module.css';
interface ButtonProps {
variant?: 'primary' | 'secondary';
}
const Button: React.FC<ButtonProps> = ({ variant = 'primary', children }) => {
const className = `${styles.button} ${styles[variant]}`;
return <button className={className}>{children}</button>;
};
构建优化配置
优化生产构建:
- 代码压缩和混淆
- 资源hash缓存策略
- 按需polyfill
// webpack.config.js 片段
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
}
}
}
}
};
监控与错误追踪
实现应用监控:
- 集成Sentry错误追踪
- 收集性能指标
- 记录用户行为分析
// 错误边界组件
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
Sentry.captureException(error, { extra: info });
}
render() {
if (this.state.hasError) {
return <FallbackUI />;
}
return this.props.children;
}
}
安全最佳实践
保障应用安全:
- 防范XSS攻击
- 处理CSRF令牌
- 验证用户输入
// 安全地渲染HTML
function SafeHTML({ html }: { html: string }) {
const sanitized = useMemo(() => {
return DOMPurify.san
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn