Appearance
文件命名规范 - React项目文件命名完全指南
1. 通用命名原则
1.1 核心原则
typescript
const namingPrinciples = {
一致性: '整个项目保持统一的命名风格',
描述性: '文件名应清晰描述其内容和用途',
可搜索性: '便于通过文件名快速查找',
避免歧义: '避免使用容易混淆的名称',
遵循约定: '遵循React和TypeScript社区约定'
};1.2 命名风格
typescript
const namingStyles = {
PascalCase: {
用途: 'React组件、类、接口、类型别名',
示例: ['Button.tsx', 'UserProfile.tsx', 'IUser.ts', 'FormData.types.ts']
},
camelCase: {
用途: '工具函数、普通变量、对象方法',
示例: ['formatDate.ts', 'validateEmail.ts', 'getUserData.ts']
},
'kebab-case': {
用途: '目录名、CSS文件、配置文件',
示例: ['user-profile/', 'button.module.css', 'jest.config.js']
},
SCREAMING_SNAKE_CASE: {
用途: '常量、环境变量',
示例: ['API_ENDPOINTS.ts', 'DEFAULT_CONFIG.ts', '.env']
}
};2. 组件文件命名
2.1 React组件
typescript
// ✅ 推荐: PascalCase
Button.tsx
Input.tsx
UserProfile.tsx
ProductCard.tsx
NavigationBar.tsx
SidebarMenu.tsx
// ❌ 不推荐
button.tsx // 应该使用PascalCase
user-profile.tsx // 应该使用PascalCase
BUTTON.tsx // 全大写不推荐
ButtonComponent.tsx // 不需要Component后缀2.2 组件目录结构
// 方式1: 单文件组件
components/
├── Button.tsx
├── Input.tsx
└── Modal.tsx
// 方式2: 目录结构 (推荐用于复杂组件)
components/
├── Button/
│ ├── Button.tsx // 主组件
│ ├── Button.test.tsx // 测试
│ ├── Button.stories.tsx // Storybook
│ ├── Button.module.css // 样式
│ ├── Button.types.ts // 类型
│ └── index.ts // 导出
├── Modal/
│ ├── Modal.tsx
│ ├── ModalHeader.tsx // 子组件
│ ├── ModalBody.tsx
│ ├── ModalFooter.tsx
│ ├── Modal.test.tsx
│ ├── Modal.types.ts
│ └── index.ts
└── UserProfile/
├── UserProfile.tsx
├── UserAvatar.tsx // 专属子组件
├── UserInfo.tsx
├── UserProfile.test.tsx
└── index.ts2.3 特殊组件命名
typescript
// 页面组件 (Page suffix可选)
HomePage.tsx // 或 Home.tsx
AboutPage.tsx // 或 About.tsx
DashboardPage.tsx // 或 Dashboard.tsx
// 布局组件
MainLayout.tsx
DashboardLayout.tsx
AuthLayout.tsx
// 容器组件 (Container suffix)
UserListContainer.tsx
ProductGridContainer.tsx
// HOC (高阶组件)
withAuth.tsx
withTheme.tsx
withErrorBoundary.tsx
// Render Props组件
MouseTracker.tsx
DataProvider.tsx3. Hook文件命名
3.1 自定义Hook
typescript
// ✅ 推荐: use + PascalCase
useAuth.ts
useTheme.ts
useLocalStorage.ts
useFetch.ts
useDebounce.ts
useWindowSize.ts
useIntersectionObserver.ts
// ❌ 不推荐
auth.ts // 缺少use前缀
UseAuth.ts // 首字母应该小写
use-auth.ts // 应该使用camelCase
authHook.ts // 不需要Hook后缀3.2 Hook目录结构
hooks/
├── useAuth.ts // 单文件Hook
├── useFetch/
│ ├── useFetch.ts // Hook实现
│ ├── useFetch.test.ts
│ ├── useFetch.types.ts
│ └── index.ts
├── useLocalStorage/
│ ├── useLocalStorage.ts
│ ├── useLocalStorage.test.ts
│ └── index.ts
└── index.ts // 统一导出3.3 Hook分类命名
typescript
// 状态管理Hooks
useStore.ts
useAppState.ts
useUserState.ts
// 数据获取Hooks
useFetch.ts
useQuery.ts
useUsers.ts
useProducts.ts
// UI交互Hooks
useToggle.ts
useModal.ts
useDropdown.ts
// 浏览器API Hooks
useLocalStorage.ts
useSessionStorage.ts
useGeolocation.ts
useMediaQuery.ts
// 工具Hooks
useDebounce.ts
useThrottle.ts
usePrevious.ts
useInterval.ts4. 类型文件命名
4.1 TypeScript类型
typescript
// 方式1: .types.ts后缀 (推荐)
user.types.ts
api.types.ts
common.types.ts
button.types.ts
// 方式2: .d.ts (声明文件)
global.d.ts
custom.d.ts
window.d.ts
// ✅ 推荐结构
types/
├── user.types.ts // 用户相关类型
├── api.types.ts // API相关类型
├── common.types.ts // 通用类型
├── product.types.ts
└── index.ts // 统一导出
// 组件内联类型
Button/
├── Button.tsx
├── Button.types.ts // 组件专属类型
└── index.ts4.2 类型文件内容
typescript
// user.types.ts
export interface User {
id: string;
name: string;
email: string;
avatar?: string;
}
export interface UserProfile extends User {
bio: string;
location: string;
website?: string;
}
export type UserRole = 'admin' | 'user' | 'guest';
export type UserStatus = 'active' | 'inactive' | 'banned';
// api.types.ts
export interface ApiResponse<T> {
data: T;
message: string;
status: number;
}
export interface ApiError {
code: string;
message: string;
details?: unknown;
}
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
pageSize: number;
}
// common.types.ts
export type Nullable<T> = T | null;
export type Optional<T> = T | undefined;
export type Maybe<T> = T | null | undefined;
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};5. 样式文件命名
5.1 CSS/SCSS文件
typescript
// CSS Modules (推荐)
Button.module.css
Input.module.css
UserProfile.module.scss
// 全局样式
global.css
variables.css
reset.css
typography.css
// 主题样式
theme.css
dark-theme.css
light-theme.css
// 工具样式
utilities.css
helpers.css5.2 Styled Components
typescript
// 方式1: .styles.ts/.styles.tsx
Button.styles.ts
Input.styles.tsx
UserProfile.styles.ts
// 方式2: styled前缀
styledButton.ts
styledInput.ts
// ✅ 推荐结构
Button/
├── Button.tsx
├── Button.styles.ts // Styled Components
├── Button.types.ts
└── index.ts
// Button.styles.ts示例
import styled from 'styled-components';
export const StyledButton = styled.button`
padding: 10px 20px;
background-color: ${props => props.theme.primary};
`;
export const ButtonText = styled.span`
font-weight: bold;
`;6. 测试文件命名
6.1 测试文件
typescript
// 单元测试
Button.test.tsx // 或 Button.spec.tsx
formatDate.test.ts // 或 formatDate.spec.ts
useAuth.test.ts
// 集成测试
UserFlow.integration.test.tsx
CartFlow.integration.test.ts
// E2E测试
login.e2e.test.ts
checkout.e2e.test.ts
// 测试工具
testUtils.ts
mockData.ts
testSetup.ts6.2 测试目录结构
// 方式1: 测试文件与源文件同目录 (推荐)
components/
├── Button/
│ ├── Button.tsx
│ ├── Button.test.tsx
│ └── index.ts
// 方式2: 独立tests目录
src/
├── components/
│ └── Button/
│ ├── Button.tsx
│ └── index.ts
└── __tests__/
└── components/
└── Button.test.tsx
// 方式3: 根目录tests
tests/
├── unit/
│ ├── components/
│ │ └── Button.test.tsx
│ └── utils/
│ └── formatDate.test.ts
├── integration/
│ └── UserFlow.test.tsx
└── e2e/
└── login.test.ts7. 工具和服务文件命名
7.1 工具函数
typescript
// utils/
formatDate.ts // camelCase
validateEmail.ts
generateId.ts
debounce.ts
throttle.ts
classNames.ts
// 数学工具
mathUtils.ts
calculations.ts
// 字符串工具
stringUtils.ts
textHelpers.ts
// ❌ 不推荐
Utils.ts // 太泛化
helper.ts // 不够描述性
functions.ts // 太泛化7.2 API服务
typescript
// services/
userApi.ts // 或 userService.ts
authApi.ts
productApi.ts
orderApi.ts
// 或按功能组织
services/
├── api/
│ ├── userApi.ts
│ ├── authApi.ts
│ └── productApi.ts
├── storage/
│ ├── localStorage.ts
│ └── sessionStorage.ts
└── analytics/
├── googleAnalytics.ts
└── trackingService.ts7.3 HTTP客户端
typescript
// API客户端
apiClient.ts
httpClient.ts
axiosInstance.ts
// 拦截器
requestInterceptor.ts
responseInterceptor.ts
errorInterceptor.ts8. 配置和常量文件
8.1 常量文件
typescript
// constants/
API_ENDPOINTS.ts // SCREAMING_SNAKE_CASE
ROUTES.ts
ERROR_MESSAGES.ts
DEFAULT_VALUES.ts
REGEX_PATTERNS.ts
// 或按功能分组
constants/
├── api/
│ ├── ENDPOINTS.ts
│ └── HEADERS.ts
├── routes/
│ └── PATHS.ts
└── validation/
└── RULES.ts8.2 配置文件
typescript
// config/
env.ts // 环境配置
theme.ts // 主题配置
i18n.ts // 国际化配置
routes.ts // 路由配置
// 第三方库配置
axiosConfig.ts
reactQueryConfig.ts
sentryConfig.ts9. 状态管理文件命名
9.1 Redux
typescript
// Redux Toolkit
store/
├── index.ts
├── hooks.ts // 类型化hooks
├── slices/
│ ├── userSlice.ts
│ ├── authSlice.ts
│ └── productSlice.ts
└── middleware/
├── loggerMiddleware.ts
└── errorMiddleware.ts
// 传统Redux
store/
├── index.ts
├── actions/
│ ├── userActions.ts
│ └── authActions.ts
├── reducers/
│ ├── userReducer.ts
│ ├── authReducer.ts
│ └── rootReducer.ts
├── selectors/
│ ├── userSelectors.ts
│ └── authSelectors.ts
└── types/
├── actionTypes.ts
└── stateTypes.ts9.2 Zustand/Jotai
typescript
// Zustand
store/
├── useUserStore.ts // use前缀
├── useAuthStore.ts
└── useCartStore.ts
// Jotai
atoms/
├── userAtoms.ts // Atoms后缀
├── authAtoms.ts
└── cartAtoms.ts10. 资源文件命名
10.1 图片文件
typescript
// 图片命名: kebab-case
assets/
├── images/
│ ├── logo.png
│ ├── user-avatar.jpg
│ ├── product-thumbnail.png
│ ├── banner-home.jpg
│ ├── icon-search.svg
│ └── icon-menu.svg
└── icons/
├── arrow-left.svg
├── arrow-right.svg
├── check-mark.svg
└── close-button.svg10.2 字体文件
typescript
assets/
└── fonts/
├── roboto-regular.woff2
├── roboto-bold.woff2
├── open-sans-regular.woff2
└── open-sans-bold.woff211. 文档文件命名
typescript
// Markdown文档
README.md
CONTRIBUTING.md
CHANGELOG.md
LICENSE.md
API.md
// 组件文档
components/
└── Button/
├── Button.tsx
├── Button.md // 组件文档
└── Button.stories.tsx12. 命名禁忌
typescript
const namingDontS = {
避免缩写: {
❌: ['usr.ts', 'btn.tsx', 'usr-prof.tsx'],
✅: ['user.ts', 'Button.tsx', 'UserProfile.tsx']
},
避免数字后缀: {
❌: ['Button1.tsx', 'Modal2.tsx', 'utils2.ts'],
✅: ['PrimaryButton.tsx', 'ConfirmModal.tsx', 'stringUtils.ts']
},
避免无意义前缀: {
❌: ['myButton.tsx', 'theModal.tsx', 'aUtils.ts'],
✅: ['Button.tsx', 'Modal.tsx', 'utils.ts']
},
避免过长名称: {
❌: ['UserProfileComponentWithAvatarAndEditButton.tsx'],
✅: ['UserProfile.tsx', 'UserProfileCard.tsx']
},
避免特殊字符: {
❌: ['user&profile.ts', 'button@v2.tsx', 'modal#new.tsx'],
✅: ['userProfile.ts', 'ButtonV2.tsx', 'NewModal.tsx']
}
};13. 命名检查清单
typescript
const namingChecklist = {
组件文件: [
'✅ 使用PascalCase',
'✅ .tsx扩展名',
'✅ 名称描述组件功能',
'✅ 避免Component后缀',
'✅ 一致的子组件命名'
],
Hook文件: [
'✅ use前缀 + camelCase',
'✅ .ts或.tsx扩展名',
'✅ 描述Hook功能',
'✅ 避免Hook后缀'
],
工具文件: [
'✅ 使用camelCase',
'✅ .ts扩展名',
'✅ 动词开头描述功能',
'✅ 避免Utils后缀'
],
类型文件: [
'✅ .types.ts后缀',
'✅ camelCase文件名',
'✅ PascalCase类型名',
'✅ 清晰的类型描述'
],
常量文件: [
'✅ SCREAMING_SNAKE_CASE',
'✅ .ts扩展名',
'✅ 描述常量用途',
'✅ 复数形式(如APIs, ROUTEs)'
],
测试文件: [
'✅ .test.ts或.spec.ts后缀',
'✅ 与源文件名称匹配',
'✅ 描述测试场景',
'✅ 组织在合理位置'
]
};14. 自动化工具
14.1 文件命名Linter
javascript
// .eslintrc.js
module.exports = {
plugins: ['filenames'],
rules: {
'filenames/match-regex': [2, '^[A-Z][a-zA-Z]*$', true], // 组件文件
'filenames/match-exported': [2, 'camel'] // 导出匹配
}
};14.2 命名验证脚本
javascript
// scripts/validate-naming.js
const fs = require('fs');
const path = require('path');
function validateComponentNaming(filePath) {
const fileName = path.basename(filePath, '.tsx');
// 检查PascalCase
if (!/^[A-Z][a-zA-Z0-9]*$/.test(fileName)) {
console.error(`❌ ${filePath}: 组件文件名应使用PascalCase`);
return false;
}
// 检查文件内容是否有同名导出
const content = fs.readFileSync(filePath, 'utf-8');
const hasExport = content.includes(`export function ${fileName}`) ||
content.includes(`export const ${fileName}`);
if (!hasExport) {
console.warn(`⚠️ ${filePath}: 文件名与导出不匹配`);
}
return true;
}
function validateHookNaming(filePath) {
const fileName = path.basename(filePath, '.ts');
// 检查use前缀
if (!fileName.startsWith('use')) {
console.error(`❌ ${filePath}: Hook文件名应以use开头`);
return false;
}
// 检查camelCase
if (!/^use[A-Z][a-zA-Z0-9]*$/.test(fileName)) {
console.error(`❌ ${filePath}: Hook文件名应使用camelCase`);
return false;
}
return true;
}15. 总结
文件命名规范的核心要点:
- 组件: PascalCase + .tsx
- Hooks: use + camelCase + .ts
- 工具: camelCase + .ts
- 类型: .types.ts后缀
- 常量: SCREAMING_SNAKE_CASE
- 样式: .module.css/.styles.ts
- 测试: .test.ts/.spec.ts
- 目录: kebab-case
保持一致的命名规范能显著提升代码可读性和团队协作效率。