frontend-dev-guidelines
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFrontend Development Guidelines
前端开发指南
Purpose
目的
Comprehensive guide for modern React development, emphasizing Suspense-based data fetching, lazy loading, proper file organization, and performance optimization.
本指南为现代React开发提供全面指导,重点介绍基于Suspense的数据获取、懒加载、规范的文件组织以及性能优化。
When to Use This Skill
适用场景
- Creating new components or pages
- Building new features
- Fetching data with TanStack Query
- Setting up routing with TanStack Router
- Styling components with MUI v7
- Performance optimization
- Organizing frontend code
- TypeScript best practices
- 创建新组件或页面
- 开发新功能模块
- 使用TanStack Query获取数据
- 使用TanStack Router配置路由
- 使用MUI v7为组件添加样式
- 性能优化
- 前端代码组织
- TypeScript最佳实践
Quick Start
快速开始
New Component Checklist
新组件检查清单
Creating a component? Follow this checklist:
- Use pattern with TypeScript
React.FC<Props> - Lazy load if heavy component:
React.lazy(() => import()) - Wrap in for loading states
<SuspenseLoader> - Use for data fetching
useSuspenseQuery - Import aliases: ,
@/,~types,~components~features - Styles: Inline if <100 lines, separate file if >100 lines
- Use for event handlers passed to children
useCallback - Default export at bottom
- No early returns with loading spinners
- Use for user notifications
useMuiSnackbar
创建组件时,请遵循以下检查清单:
- 使用TypeScript模式
React.FC<Props> - 若为大型组件,启用懒加载:
React.lazy(() => import()) - 使用包裹以处理加载状态
<SuspenseLoader> - 使用进行数据获取
useSuspenseQuery - 使用导入别名:,
@/,~types,~components~features - 样式规则:代码少于100行时内联编写,超过100行时使用单独文件
- 传递给子组件的事件处理器使用包裹
useCallback - 在文件底部使用默认导出
- 避免通过提前返回实现加载动画
- 使用实现用户通知
useMuiSnackbar
New Feature Checklist
新功能模块检查清单
Creating a feature? Set up this structure:
- Create directory
features/{feature-name}/ - Create subdirectories: ,
api/,components/,hooks/,helpers/types/ - Create API service file:
api/{feature}Api.ts - Set up TypeScript types in
types/ - Create route in
routes/{feature-name}/index.tsx - Lazy load feature components
- Use Suspense boundaries
- Export public API from feature
index.ts
开发功能模块时,请按以下结构搭建:
- 创建目录
features/{feature-name}/ - 创建子目录:,
api/,components/,hooks/,helpers/types/ - 创建API服务文件:
api/{feature}Api.ts - 在目录中定义TypeScript类型
types/ - 在中配置路由
routes/{feature-name}/index.tsx - 懒加载功能模块组件
- 使用Suspense边界
- 在功能模块的中导出公共API
index.ts
Import Aliases Quick Reference
导入别名速查
| Alias | Resolves To | Example |
|---|---|---|
| | |
| | |
| | |
| | |
Defined in: vite.config.ts lines 180-185
| 别名 | 对应路径 | 示例 |
|---|---|---|
| | |
| | |
| | |
| | |
定义位置:vite.config.ts 第180-185行
Common Imports Cheatsheet
常用导入代码片段
typescript
// React & Lazy Loading
import React, { useState, useCallback, useMemo } from 'react';
const Heavy = React.lazy(() => import('./Heavy'));
// MUI Components
import { Box, Paper, Typography, Button, Grid } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
// TanStack Query (Suspense)
import { useSuspenseQuery, useQueryClient } from '@tanstack/react-query';
// TanStack Router
import { createFileRoute } from '@tanstack/react-router';
// Project Components
import { SuspenseLoader } from '~components/SuspenseLoader';
// Hooks
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
// Types
import type { Post } from '~types/post';typescript
// React & 懒加载
import React, { useState, useCallback, useMemo } from 'react';
const Heavy = React.lazy(() => import('./Heavy'));
// MUI 组件
import { Box, Paper, Typography, Button, Grid } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
// TanStack Query (Suspense)
import { useSuspenseQuery, useQueryClient } from '@tanstack/react-query';
// TanStack Router
import { createFileRoute } from '@tanstack/react-router';
// 项目组件
import { SuspenseLoader } from '~components/SuspenseLoader';
// 自定义Hooks
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
// 类型定义
import type { Post } from '~types/post';Topic Guides
主题指南
🎨 Component Patterns
🎨 组件设计模式
Modern React components use:
- for type safety
React.FC<Props> - for code splitting
React.lazy() - for loading states
SuspenseLoader - Named const + default export pattern
Key Concepts:
- Lazy load heavy components (DataGrid, charts, editors)
- Always wrap lazy components in Suspense
- Use SuspenseLoader component (with fade animation)
- Component structure: Props → Hooks → Handlers → Render → Export
📖 Complete Guide: resources/component-patterns.md
现代React组件采用以下规范:
- 使用保证类型安全
React.FC<Props> - 使用实现代码分割
React.lazy() - 使用处理加载状态
SuspenseLoader - 采用“命名常量+默认导出”模式
核心概念:
- 对大型组件(DataGrid、图表、编辑器)启用懒加载
- 懒加载组件必须包裹在Suspense中
- 使用带淡入动画的SuspenseLoader组件
- 组件结构:Props定义 → Hooks调用 → 事件处理器 → 渲染逻辑 → 导出
📖 完整指南:resources/component-patterns.md
📊 Data Fetching
📊 数据获取
PRIMARY PATTERN: useSuspenseQuery
- Use with Suspense boundaries
- Cache-first strategy (check grid cache before API)
- Replaces checks
isLoading - Type-safe with generics
API Service Layer:
- Create
features/{feature}/api/{feature}Api.ts - Use axios instance
apiClient - Centralized methods per feature
- Route format: (NOT
/form/route)/api/form/route
📖 Complete Guide: resources/data-fetching.md
首选模式:useSuspenseQuery
- 配合Suspense边界使用
- 缓存优先策略(先检查缓存再调用API)
- 替代状态检查
isLoading - 通过泛型保证类型安全
API服务层规范:
- 创建文件
features/{feature}/api/{feature}Api.ts - 使用axios实例
apiClient - 按功能模块集中管理API方法
- 路由格式:(禁止使用
/form/route)/api/form/route
📖 完整指南:resources/data-fetching.md
📁 File Organization
📁 文件组织
features/ vs components/:
- : Domain-specific (posts, comments, auth)
features/ - : Truly reusable (SuspenseLoader, CustomAppBar)
components/
Feature Subdirectories:
features/
my-feature/
api/ # API service layer
components/ # Feature components
hooks/ # Custom hooks
helpers/ # Utility functions
types/ # TypeScript types📖 Complete Guide: resources/file-organization.md
features/ 与 components/ 区别:
- : 领域特定模块(帖子、评论、权限验证)
features/ - : 通用可复用组件(SuspenseLoader、CustomAppBar)
components/
功能模块子目录结构:
features/
my-feature/
api/ # API服务层
components/ # 功能模块专属组件
hooks/ # 自定义Hooks
helpers/ # 工具函数
types/ # TypeScript类型定义📖 完整指南:resources/file-organization.md
🎨 Styling
🎨 样式编写
Inline vs Separate:
- <100 lines: Inline
const styles: Record<string, SxProps<Theme>> -
100 lines: Separatefile
.styles.ts
Primary Method:
- Use prop for MUI components
sx - Type-safe with
SxProps<Theme> - Theme access:
(theme) => theme.palette.primary.main
MUI v7 Grid:
typescript
<Grid size={{ xs: 12, md: 6 }}> // ✅ v7 syntax
<Grid xs={12} md={6}> // ❌ Old syntax📖 Complete Guide: resources/styling-guide.md
内联与分离规则:
- 代码少于100行:使用内联
const styles: Record<string, SxProps<Theme>> - 代码超过100行:使用单独的文件
.styles.ts
首选方式:
- 为MUI组件使用属性
sx - 通过保证类型安全
SxProps<Theme> - 主题访问:
(theme) => theme.palette.primary.main
MUI v7 Grid语法:
typescript
<Grid size={{ xs: 12, md: 6 }}> // ✅ v7 正确语法
<Grid xs={12} md={6}> // ❌ 旧版语法📖 完整指南:resources/styling-guide.md
🛣️ Routing
🛣️ 路由配置
TanStack Router - Folder-Based:
- Directory:
routes/my-route/index.tsx - Lazy load components
- Use
createFileRoute - Breadcrumb data in loader
Example:
typescript
import { createFileRoute } from '@tanstack/react-router';
import { lazy } from 'react';
const MyPage = lazy(() => import('@/features/my-feature/components/MyPage'));
export const Route = createFileRoute('/my-route/')({
component: MyPage,
loader: () => ({ crumb: 'My Route' }),
});📖 Complete Guide: resources/routing-guide.md
TanStack Router - 基于目录的路由:
- 目录结构:
routes/my-route/index.tsx - 懒加载组件
- 使用创建路由
createFileRoute - 在loader中配置面包屑数据
示例:
typescript
import { createFileRoute } from '@tanstack/react-router';
import { lazy } from 'react';
const MyPage = lazy(() => import('@/features/my-feature/components/MyPage'));
export const Route = createFileRoute('/my-route/')({
component: MyPage,
loader: () => ({ crumb: '我的路由' }),
});📖 完整指南:resources/routing-guide.md
⏳ Loading & Error States
⏳ 加载与错误状态
CRITICAL RULE: No Early Returns
typescript
// ❌ NEVER - Causes layout shift
if (isLoading) {
return <LoadingSpinner />;
}
// ✅ ALWAYS - Consistent layout
<SuspenseLoader>
<Content />
</SuspenseLoader>Why: Prevents Cumulative Layout Shift (CLS), better UX
Error Handling:
- Use for user feedback
useMuiSnackbar - NEVER
react-toastify - TanStack Query callbacks
onError
📖 Complete Guide: resources/loading-and-error-states.md
核心规则:禁止提前返回
typescript
// ❌ 绝对禁止 - 会导致布局偏移
if (isLoading) {
return <LoadingSpinner />;
}
// ✅ 正确方式 - 保持布局稳定
<SuspenseLoader>
<Content />
</SuspenseLoader>原因: 避免累积布局偏移(CLS),提升用户体验
错误处理:
- 使用提供用户反馈
useMuiSnackbar - 禁止使用
react-toastify - 通过TanStack Query的回调处理错误
onError
📖 完整指南:resources/loading-and-error-states.md
⚡ Performance
⚡ 性能优化
Optimization Patterns:
- : Expensive computations (filter, sort, map)
useMemo - : Event handlers passed to children
useCallback - : Expensive components
React.memo - Debounced search (300-500ms)
- Memory leak prevention (cleanup in useEffect)
📖 Complete Guide: resources/performance.md
优化模式:
- : 处理昂贵计算(过滤、排序、映射)
useMemo - : 传递给子组件的事件处理器
useCallback - : 优化大型组件性能
React.memo - 搜索输入防抖(300-500ms)
- 内存泄漏预防(在useEffect中清理)
📖 完整指南:resources/performance.md
📘 TypeScript
📘 TypeScript规范
Standards:
- Strict mode, no type
any - Explicit return types on functions
- Type imports:
import type { User } from '~types/user' - Component prop interfaces with JSDoc
📖 Complete Guide: resources/typescript-standards.md
标准要求:
- 启用严格模式,禁止使用类型
any - 函数必须显式声明返回类型
- 类型导入使用
import type { User } from '~types/user' - 组件Props接口需添加JSDoc注释
📖 完整指南:resources/typescript-standards.md
🔧 Common Patterns
🔧 通用模式
Covered Topics:
- React Hook Form with Zod validation
- DataGrid wrapper contracts
- Dialog component standards
- hook for current user
useAuth - Mutation patterns with cache invalidation
📖 Complete Guide: resources/common-patterns.md
涵盖主题:
- 结合Zod校验的React Hook Form
- DataGrid封装规范
- Dialog组件标准
- 获取当前用户的Hook
useAuth - 带缓存失效的Mutation模式
📖 完整指南:resources/common-patterns.md
📚 Complete Examples
📚 完整示例
Full working examples:
- Modern component with all patterns
- Complete feature structure
- API service layer
- Route with lazy loading
- Suspense + useSuspenseQuery
- Form with validation
📖 Complete Guide: resources/complete-examples.md
可运行的完整示例:
- 包含所有最佳实践的现代组件
- 完整的功能模块结构
- API服务层实现
- 带懒加载的路由配置
- Suspense + useSuspenseQuery组合
- 带校验的表单
📖 完整指南:resources/complete-examples.md
Navigation Guide
导航指南
| Need to... | Read this resource |
|---|---|
| Create a component | component-patterns.md |
| Fetch data | data-fetching.md |
| Organize files/folders | file-organization.md |
| Style components | styling-guide.md |
| Set up routing | routing-guide.md |
| Handle loading/errors | loading-and-error-states.md |
| Optimize performance | performance.md |
| TypeScript types | typescript-standards.md |
| Forms/Auth/DataGrid | common-patterns.md |
| See full examples | complete-examples.md |
| 需求场景 | 参考资源 |
|---|---|
| 创建组件 | component-patterns.md |
| 数据获取 | data-fetching.md |
| 文件/目录组织 | file-organization.md |
| 组件样式编写 | styling-guide.md |
| 路由配置 | routing-guide.md |
| 加载/错误状态处理 | loading-and-error-states.md |
| 性能优化 | performance.md |
| TypeScript类型规范 | typescript-standards.md |
| 表单/权限/DataGrid | common-patterns.md |
| 查看完整示例 | complete-examples.md |
Core Principles
核心原则
- Lazy Load Everything Heavy: Routes, DataGrid, charts, editors
- Suspense for Loading: Use SuspenseLoader, not early returns
- useSuspenseQuery: Primary data fetching pattern for new code
- Features are Organized: api/, components/, hooks/, helpers/ subdirs
- Styles Based on Size: <100 inline, >100 separate
- Import Aliases: Use @/, ~types, ~components, ~features
- No Early Returns: Prevents layout shift
- useMuiSnackbar: For all user notifications
- 大型组件全部懒加载:路由、DataGrid、图表、编辑器
- 使用Suspense处理加载状态:使用SuspenseLoader,禁止提前返回
- useSuspenseQuery为首选数据获取模式:新代码统一使用该模式
- 功能模块结构化:包含api/、components/、hooks/、helpers/子目录
- 按代码量选择样式方式:少于100行内联,超过100行分离
- 使用导入别名:统一使用@/、~types、~components、~features
- 禁止提前返回:避免布局偏移
- 统一使用useMuiSnackbar:所有用户通知均使用该方式
Quick Reference: File Structure
文件结构速查
src/
features/
my-feature/
api/
myFeatureApi.ts # API service
components/
MyFeature.tsx # Main component
SubComponent.tsx # Related components
hooks/
useMyFeature.ts # Custom hooks
useSuspenseMyFeature.ts # Suspense hooks
helpers/
myFeatureHelpers.ts # Utilities
types/
index.ts # TypeScript types
index.ts # Public exports
components/
SuspenseLoader/
SuspenseLoader.tsx # Reusable loader
CustomAppBar/
CustomAppBar.tsx # Reusable app bar
routes/
my-route/
index.tsx # Route component
create/
index.tsx # Nested routesrc/
features/
my-feature/
api/
myFeatureApi.ts # API服务文件
components/
MyFeature.tsx # 主组件
SubComponent.tsx # 相关组件
hooks/
useMyFeature.ts # 自定义Hook
useSuspenseMyFeature.ts # Suspense Hook
helpers/
myFeatureHelpers.ts # 工具函数
types/
index.ts # TypeScript类型定义
index.ts # 公共导出入口
components/
SuspenseLoader/
SuspenseLoader.tsx # 可复用加载组件
CustomAppBar/
CustomAppBar.tsx # 可复用导航栏
routes/
my-route/
index.tsx # 路由组件
create/
index.tsx # 嵌套路由Modern Component Template (Quick Copy)
现代组件模板(快速复制)
typescript
import React, { useState, useCallback } from 'react';
import { Box, Paper } from '@mui/material';
import { useSuspenseQuery } from '@tanstack/react-query';
import { featureApi } from '../api/featureApi';
import type { FeatureData } from '~types/feature';
interface MyComponentProps {
id: number;
onAction?: () => void;
}
export const MyComponent: React.FC<MyComponentProps> = ({ id, onAction }) => {
const [state, setState] = useState<string>('');
const { data } = useSuspenseQuery({
queryKey: ['feature', id],
queryFn: () => featureApi.getFeature(id),
});
const handleAction = useCallback(() => {
setState('updated');
onAction?.();
}, [onAction]);
return (
<Box sx={{ p: 2 }}>
<Paper sx={{ p: 3 }}>
{/* Content */}
</Paper>
</Box>
);
};
export default MyComponent;For complete examples, see resources/complete-examples.md
typescript
import React, { useState, useCallback } from 'react';
import { Box, Paper } from '@mui/material';
import { useSuspenseQuery } from '@tanstack/react-query';
import { featureApi } from '../api/featureApi';
import type { FeatureData } from '~types/feature';
interface MyComponentProps {
id: number;
onAction?: () => void;
}
export const MyComponent: React.FC<MyComponentProps> = ({ id, onAction }) => {
const [state, setState] = useState<string>('');
const { data } = useSuspenseQuery({
queryKey: ['feature', id],
queryFn: () => featureApi.getFeature(id),
});
const handleAction = useCallback(() => {
setState('updated');
onAction?.();
}, [onAction]);
return (
<Box sx={{ p: 2 }}>
<Paper sx={{ p: 3 }}>
{/* 内容区域 */}
</Paper>
</Box>
);
};
export default MyComponent;查看完整示例请参考 resources/complete-examples.md
Related Skills
相关技能
- error-tracking: Error tracking with Sentry (applies to frontend too)
- backend-dev-guidelines: Backend API patterns that frontend consumes
Skill Status: Modular structure with progressive loading for optimal context management
- error-tracking: 基于Sentry的错误追踪(同样适用于前端)
- backend-dev-guidelines: 前端调用的后端API设计模式
技能状态: 模块化结构,支持渐进式加载,优化上下文管理