团队协作流程
工程化规范的必要性
工程化规范是团队协作的基石。缺乏统一标准会导致代码风格混乱、维护成本激增、协作效率低下。一个典型的例子是缩进问题:有人用2空格,有人用4空格,甚至混用制表符和空格。这种差异在代码合并时会产生大量无意义的冲突。
// 不良示例:混合缩进风格
function badExample(){
const x = 1;
const y = 2;
return x + y;
}
// 良好示例:统一2空格缩进
function goodExample() {
const x = 1;
const y = 2;
return x + y;
}
代码风格统一方案
ESLint配置
ESLint是最流行的JavaScript静态检查工具。团队应该共享同一份配置文件:
// .eslintrc.js
module.exports = {
extends: ['airbnb-base'],
rules: {
'indent': ['error', 2],
'quotes': ['error', 'single'],
'semi': ['error', 'always'],
'no-console': 'warn',
'max-len': ['error', { code: 100 }]
},
parserOptions: {
ecmaVersion: 2021
}
};
Prettier集成
Prettier作为代码格式化工具,可以与ESLint配合使用:
// .prettierrc
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "es5"
}
在package.json中添加格式化脚本:
{
"scripts": {
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,scss,json,md}\""
}
}
Git工作流设计
分支管理策略
推荐使用Git Flow的变种策略:
main
- 生产环境代码develop
- 集成开发分支feature/*
- 功能开发分支hotfix/*
- 紧急修复分支
# 示例工作流
git checkout -b feature/user-auth develop
# 开发完成后
git checkout develop
git merge --no-ff feature/user-auth
Commit Message规范
采用Angular提交规范:
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
示例:
feat(user): add login API endpoint
- Implement JWT authentication
- Add login route handler
- Write unit tests
Closes #123
自动化流程建设
CI/CD管道配置
GitHub Actions示例配置:
# .github/workflows/ci.yml
name: CI Pipeline
on: [push, pull_request]
jobs:
test:
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 test
自动化测试策略
测试金字塔实践:
- 单元测试(Jest)
- 集成测试(Testing Library)
- E2E测试(Cypress)
// 单元测试示例
describe('sum module', () => {
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
});
文档规范体系
代码注释标准
使用JSDoc规范:
/**
* Calculates the sum of two numbers
* @param {number} a - The first number
* @param {number} b - The second number
* @returns {number} The sum of a and b
* @example
* // returns 5
* sum(2, 3)
*/
function sum(a, b) {
return a + b;
}
项目文档结构
标准文档目录:
docs/
├── ARCHITECTURE.md # 系统架构
├── API.md # API文档
├── DEVELOPMENT.md # 开发指南
└── CHANGELOG.md # 变更日志
组件开发规范
组件设计原则
- 单一职责原则
- 受控组件优先
- 明确的props接口
React组件示例:
// Button.jsx
import PropTypes from 'prop-types';
/**
* Primary UI component for user interaction
*/
export const Button = ({
primary = false,
size = 'medium',
label,
...props
}) => {
const mode = primary ? 'btn-primary' : 'btn-secondary';
return (
<button
type="button"
className={['btn', `btn-${size}`, mode].join(' ')}
{...props}
>
{label}
</button>
);
};
Button.propTypes = {
primary: PropTypes.bool,
size: PropTypes.oneOf(['small', 'medium', 'large']),
label: PropTypes.string.isRequired,
onClick: PropTypes.func,
};
性能监控方案
性能指标收集
使用web-vitals库:
import { getCLS, getFID, getLCP } from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
navigator.sendBeacon('/analytics', body);
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);
错误追踪
Sentry集成示例:
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
Sentry.init({
dsn: 'YOUR_DSN',
integrations: [new BrowserTracing()],
tracesSampleRate: 0.2,
release: 'my-project@1.0.0'
});
// 边界错误捕获
<Sentry.ErrorBoundary fallback={<p>An error occurred</p>}>
<MyComponent />
</Sentry.ErrorBoundary>
依赖管理策略
版本锁定机制
使用package-lock.json或yarn.lock确保依赖一致性:
# 安装时使用精确版本
npm install --save-exact react@18.2.0
依赖更新流程
- 定期执行
npm outdated
- 使用npm-check-updates工具:
npx npm-check-updates -u
npm install
npm test
代码审查标准
审查清单示例
- 功能实现是否符合需求
- 是否有适当的测试覆盖
- 代码是否符合风格指南
- 是否存在性能问题
- 错误处理是否完备
审查工具集成
GitHub PR模板示例:
## 变更描述
## 影响范围
## 测试建议
## 相关Issue
前端架构决策
技术选型记录
使用ADR(Architecture Decision Record)文档:
# 1. 状态管理方案选择
## 决策
选用Zustand而非Redux作为状态管理方案
## 理由
- 更简单的API
- 更少的样板代码
- 更好的TypeScript支持
- 满足当前项目复杂度需求
## 后果
- 团队需要学习新API
- 生态系统不如Redux丰富
异常处理机制
错误边界实现
React错误边界示例:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
logErrorToService(error, info);
}
render() {
if (this.state.hasError) {
return <FallbackUI />;
}
return this.props.children;
}
}
国际化方案
i18n实现策略
使用i18next的React集成:
// i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'i18next/react';
i18n
.use(initReactI18next)
.init({
resources: {
en: {
translation: {
welcome: 'Welcome'
}
},
zh: {
translation: {
welcome: '欢迎'
}
}
},
lng: 'en',
fallbackLng: 'en'
});
// 组件中使用
function App() {
const { t } = useTranslation();
return <h1>{t('welcome')}</h1>;
}
样式管理方案
CSS模块化实践
使用CSS Modules:
/* Button.module.css */
.primary {
background: blue;
}
.button {
padding: 0.5rem 1rem;
}
import styles from './Button.module.css';
function Button({ primary }) {
return (
<button className={`${styles.button} ${primary ? styles.primary : ''}`}>
Click
</button>
);
}
类型安全实践
TypeScript配置
推荐tsconfig配置:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"jsx": "react-jsx",
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"]
}
类型定义示例
React组件props类型:
interface ButtonProps {
/**
* 是否为主要按钮
*/
primary?: boolean;
/**
* 按钮尺寸
*/
size?: 'small' | 'medium' | 'large';
/**
* 按钮文本
*/
label: string;
/**
* 点击事件处理
*/
onClick?: () => void;
}
const Button: FC<ButtonProps> = ({ primary = false, size = 'medium', label }) => {
// 组件实现
};
构建优化策略
代码分割配置
Webpack动态导入:
// 静态导入
import Home from './Home';
// 动态导入
const About = lazy(() => import('./About'));
// webpack配置
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
path: path.resolve(__dirname, 'dist'),
clean: true
}
打包分析工具
使用webpack-bundle-analyzer:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: 'bundle-report.html',
openAnalyzer: false
})
]
};
环境变量管理
多环境配置
使用dotenv管理环境变量:
# .env.development
API_BASE_URL=http://localhost:3000
DEBUG=true
# .env.production
API_BASE_URL=https://api.example.com
// webpack配置环境变量
plugins: [
new webpack.DefinePlugin({
'process.env.API_BASE_URL': JSON.stringify(process.env.API_BASE_URL)
})
]
包发布规范
私有包发布流程
- 版本号遵循semver规范
- 更新CHANGELOG.md
- 添加访问控制
# 发布前准备
npm version patch -m "Bump version to %s"
git push --follow-tags
# 发布
npm publish --access restricted
移动端适配方案
响应式设计实现
使用CSS媒体查询与相对单位:
.container {
padding: 1rem;
width: 100%;
}
@media (min-width: 768px) {
.container {
max-width: 720px;
margin: 0 auto;
}
}
视口配置
HTML meta标签:
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
浏览器兼容策略
Polyfill方案
使用core-js和regenerator-runtime:
// polyfills.js
import 'core-js/stable';
import 'regenerator-runtime/runtime';
// webpack入口配置
entry: ['@babel/polyfill', './src/index.js']
兼容性检测
添加browserslist配置:
# .browserslistrc
last 2 versions
> 1%
not dead
not IE 11
状态管理规范
Redux最佳实践
- 使用Redux Toolkit
- 不可变更新
- 选择器记忆化
// store.js
import { configureStore } from '@reduxjs/toolkit';
export const store = configureStore({
reducer: {
counter: counterReducer
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(logger)
});
// slice示例
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state) => state + 1
}
});
前端安全实践
XSS防护措施
- 使用DOMPurify清理HTML
- React默认转义
- CSP策略
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(userInput);
CSRF防护
添加CSRF Token:
// 后端设置cookie
res.cookie('XSRF-TOKEN', token, {
httpOnly: false // 让前端可以读取
});
// 前端发送请求时带上
axios.defaults.headers.common['X-XSRF-TOKEN'] = getCookie('XSRF-TOKEN');
设计系统集成
Storybook配置
组件文档化示例:
// Button.stories.js
export default {
title: 'Components/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' }
}
};
const Template = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button'
};
服务端渲染规范
Next.js页面约定
文件系统路由:
pages/
├── _app.js # 应用壳
├── _document.js # HTML模板
├── index.js # 首页路由
└── about.js # /about路由
数据获取方法
getServerSideProps示例:
export async function getServerSideProps(context) {
const res = await fetch(`https://api.example.com/data`);
const data = await res.json();
if (!data) {
return {
notFound: true
};
}
return {
props: { data }
};
}
微前端架构
模块联邦配置
Webpack 5 Module Federation:
// app1 webpack.config.js
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button'
},
shared: ['react', 'react-dom']
});
// app2 webpack.config.js
new ModuleFederationPlugin({
name: 'app2',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js'
},
shared: ['react', 'react-dom']
});
可视化规范
图表库选择标准
- 性能考量
- 可访问性支持
- 维护活跃度
ECharts配置示例:
option = {
title: {
text: '销售趋势'
},
tooltip: {},
xAxis: {
data: ['1月', '2月', '3月']
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36]
}]
};
动画实现原则
CSS动画最佳实践
- 优先使用transform和opacity
- 避免布局抖动
- 使用will-change优化
.box {
transition: transform 0.3s ease-out;
will-change: transform;
}
.box:hover {
transform: scale(1.05);
}
JavaScript动画
使用requestAnimationFrame:
function animate() {
element.style.transform = `translateX(${position}px)`;
position += 1;
if (position < 100) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
前端存储方案
本地存储策略
- 敏感数据不存储
- 添加版本控制
- 大小限制考虑
// 带版本控制的localStorage封装
const storage = {
set(key, value) {
localStorage.setItem(key, JSON.stringify({
version: 1,
data: value
}));
},
get(key) {
const item = JSON.parse(localStorage.getItem(key));
if (item?.version === 1) {
return item.data;
}
return null;
}
};
性能优化指标
Core Web Vitals
- LCP (Largest Contentful Paint)
- FID (First Input Delay)
- CLS (Cumulative Layout Shift)
优化LCP示例:
<!-- 预加载关键资源 -->
<link rel="preload" href="hero-image.jpg" as="image">
<!-- 懒加载非关键图片 -->
<img src="placeholder.jpg" data-src="actual.jpg" loading="lazy">
可访问性标准
ARIA实践指南
- 语义化HTML优先
- 必要时补充ARIA属性
- 键盘导航测试
<button
aria-label="关闭弹窗"
aria-expanded="false"
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn