作为 Vue 开发者,在迁移到 React 开发时,除了开发过程中的差异,部署和持续集成的策略也需要相应调整。本文将详细介绍 React 项目的部署流程和持续集成最佳实践。
构建流程对比
Vue 的构建流程
在 Vue 项目中,我们通常使用:
- Vue CLI 或 Vite 构建工具
npm run build
生成生产环境代码- 输出目录通常是
dist
# Vue CLI
npm run build
# 输出到 dist 目录
# Vite
npm run build
# 输出到 dist 目录
React 的构建流程
在 React 项目中,我们主要使用:
- Create React App (CRA) 或 Vite
npm run build
生成生产环境代码- 输出目录是
build
(CRA)或dist
(Vite)
# Create React App
npm run build
# 输出到 build 目录
# Vite + React
npm run build
# 输出到 dist 目录
主要区别:
构建工具
- Vue CLI 专注于 Vue 生态
- CRA 专注于 React 生态
配置方式
- Vue CLI 提供 vue.config.js
- CRA 需要 eject 或使用 craco
输出目录
- Vue 统一使用 dist
- React 根据工具有所不同
环境配置
1. 环境变量
# .env
REACT_APP_API_URL=https://api.example.com
REACT_APP_ENV=production
# .env.development
REACT_APP_API_URL=http://localhost:3000
REACT_APP_ENV=development
# .env.test
REACT_APP_API_URL=http://test-api.example.com
REACT_APP_ENV=test
2. 构建配置
// craco.config.js
module.exports = {
webpack: {
configure: (webpackConfig) => {
// 自定义 webpack 配置
return webpackConfig;
},
plugins: [
// 添加额外的 webpack 插件
]
},
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
}
};
部署策略
1. 静态部署
# Nginx 配置
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://api.example.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
2. Docker 部署
# Dockerfile
# 构建阶段
FROM node:16 as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
3. 容器编排
# docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- "80:80"
environment:
- NODE_ENV=production
- REACT_APP_API_URL=https://api.example.com
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- app-network
api:
image: api-service
ports:
- "3000:3000"
environment:
- NODE_ENV=production
networks:
- app-network
networks:
app-network:
driver: bridge
持续集成/持续部署 (CI/CD)
1. GitHub Actions
# .github/workflows/ci.yml
name: React CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Deploy to production
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
2. GitLab CI/CD
# .gitlab-ci.yml
image: node:16
stages:
- test
- build
- deploy
cache:
paths:
- node_modules/
test:
stage: test
script:
- npm ci
- npm test
build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- build/
deploy:production:
stage: deploy
script:
- apt-get update -qy
- apt-get install -y rsync
- rsync -avz --delete build/ user@server:/var/www/html/
only:
- main
性能优化
1. 代码分割
// App.js
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<Profile />} />
</Routes>
</Suspense>
);
}
2. 资源优化
// craco.config.js
const CompressionPlugin = require('compression-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
webpack: {
plugins: [
// Gzip 压缩
new CompressionPlugin({
test: /\.(js|css|html|svg)$/,
algorithm: 'gzip'
}),
// 包分析
process.env.ANALYZE && new BundleAnalyzerPlugin()
].filter(Boolean)
}
};
监控与日志
1. 错误监控
// ErrorBoundary.js
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 发送错误到监控服务
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
2. 性能监控
// performance.js
export const initPerformanceMonitoring = () => {
// 监控页面加载性能
window.addEventListener('load', () => {
const timing = performance.getEntriesByType('navigation')[0];
const metrics = {
DNS: timing.domainLookupEnd - timing.domainLookupStart,
TCP: timing.connectEnd - timing.connectStart,
TTFB: timing.responseStart - timing.requestStart,
contentLoad: timing.domContentLoadedEventEnd - timing.navigationStart,
load: timing.loadEventEnd - timing.navigationStart
};
// 发送性能数据到监控服务
sendMetricsToService(metrics);
});
};
安全考虑
内容安全策略 (CSP)
# Nginx 配置 add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';";
HTTPS 配置
server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; } }
部署检查清单
构建优化
- 移除开发依赖
- 优化包大小
- 启用代码分割
- 配置缓存策略
环境配置
- 检查环境变量
- 验证 API 配置
- 确认路由配置
- 测试代理设置
性能检查
- 运行性能测试
- 检查加载时间
- 验证缓存策略
- 确认资源优化
安全检查
- 启用 HTTPS
- 配置 CSP
- 检查依赖漏洞
- 验证认证流程
小结
React 部署的特点:
- 工具链完善
- 配置灵活
- 性能优先
- 安全可靠
从 Vue 到 React 的转变:
- 适应新的构建工具
- 掌握部署策略
- 理解性能优化
- 实践安全措施
开发建议:
- 自动化部署
- 持续监控
- 定期优化
- 安全第一
至此,我们已经完成了从 Vue 到 React 的完整学习路径。希望这个系列的文章能够帮助你更好地理解和使用 React,构建出高质量的应用。
如果觉得这篇文章对你有帮助,别忘了点个赞 👍
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。