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/{功能名称}/ - 创建子目录:、
api/、components/、hooks/、helpers/types/ - 创建 API 服务文件:
api/{功能名称}Api.ts - 在 目录中配置 TypeScript 类型定义
types/ - 在 中配置路由
routes/{功能名称}/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/{功能名}/api/{功能名}Api.ts - 使用 axios 实例
apiClient - 按功能集中维护接口方法
- 路由格式:(不要用
/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、自定义导航栏)
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 组件使用 prop 定义样式
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 # 自定义Hooks
useSuspenseMyFeature.ts # Suspense相关Hooks
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模式规范
技能状态:模块化结构,支持渐进式加载,可实现最优上下文管理