WebBuild&Deploy(React)Skill web-build-deploy

这份指南提供了构建和部署React应用程序的详细步骤,包括Vercel和Netlify的部署指南、Docker部署、GitHub Actions CI/CD工作流、环境变量配置、构建优化技巧以及健康检查和监控设置。

前端开发 0 次安装 0 次浏览 更新于 3/3/2026

name: web-build-deploy description: 构建和部署React网络应用。用于配置构建、部署到Vercel/Netlify、设置CI/CD、Docker或管理环境。

Web Build & Deploy (React)

Vercel 部署

快速部署

# 安装 Vercel CLI
npm i -g vercel

# 部署
vercel

# 部署到生产环境
vercel --prod

配置 (vercel.json)

{
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "framework": "vite",
  "rewrites": [
    { "source": "/(.*)", "destination": "/" }
  ],
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "X-Frame-Options", "value": "DENY" }
      ]
    }
  ]
}

环境变量

# 通过 CLI 添加
vercel env add NEXT_PUBLIC_API_URL

# 或在 Vercel 仪表板:设置 > 环境变量

# 在代码中访问
const apiUrl = process.env.NEXT_PUBLIC_API_URL;

预览部署

每次推送到分支会自动创建预览URL:

  • https://project-git-branch-username.vercel.app

Netlify 部署

快速部署

# 安装 Netlify CLI
npm i -g netlify-cli

# 登录
netlify login

# 部署预览
netlify deploy

# 部署到生产环境
netlify deploy --prod

配置 (netlify.toml)

[build]
  command = "npm run build"
  publish = "dist"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"

[build.environment]
  NODE_VERSION = "18"

环境变量

# 通过 CLI 添加
netlify env:set API_URL https://api.example.com

# 或在 Netlify 仪表板:站点设置 > 环境变量

Docker 部署

Dockerfile (多阶段构建)

# 构建阶段
FROM node:18-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

# 生产阶段
FROM nginx:alpine

# 复制构建文件
COPY --from=builder /app/dist /usr/share/nginx/html

# 复制 nginx 配置以支持 SPA 路由
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

nginx.conf (SPA 路由)

server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

    # 缓存静态资源
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # SPA 回退
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 安全头信息
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
}

Docker Compose

# docker-compose.yml
version: '3.8'

services:
  web:
    build: .
    ports:
      - "80:80"
    environment:
      - NODE_ENV=production
    restart: unless-stopped

  # 带后端
  api:
    build: ./backend
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/app
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=app

volumes:
  postgres_data:

构建 & 运行

# 构建镜像
docker build -t myapp:latest .

# 运行容器
docker run -p 80:80 myapp:latest

# 使用 docker-compose
docker-compose up -d
docker-compose down

GitHub Actions CI/CD

基本工作流

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build
        env:
          VITE_API_URL: ${{ secrets.API_URL }}

      - name: Deploy to Vercel
        if: github.ref == 'refs/heads/main'
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'

带预览部署

name: Preview

on: [pull_request]

jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy Preview
        uses: amondnet/vercel-action@v25
        id: deploy
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}

      - name: Comment PR
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '🚀 Preview deployed to: ${{ steps.deploy.outputs.preview-url }}'
            })

环境配置

Vite

// vite.config.ts
import { defineConfig, loadEnv } from 'vite';

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '');

  return {
    define: {
      'process.env.API_URL': JSON.stringify(env.VITE_API_URL),
    },
  };
});
# .env.development
VITE_API_URL=http://localhost:8000

# .env.production
VITE_API_URL=https://api.example.com

Next.js

# .env.local (不提交)
DATABASE_URL=postgresql://localhost:5432/dev

# .env.production
NEXT_PUBLIC_API_URL=https://api.example.com
// 在代码中访问
// 客户端(必须以 NEXT_PUBLIC_ 开头)
const apiUrl = process.env.NEXT_PUBLIC_API_URL;

// 仅服务器端
const dbUrl = process.env.DATABASE_URL;

构建优化

Vite 构建分析

# 安装分析器
npm i -D rollup-plugin-visualizer

# 添加到 vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  plugins: [
    visualizer({
      filename: 'stats.html',
      open: true,
    }),
  ],
});

# 构建和分析
npm run build

代码分割

// 基于路由的分割
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

// 组件分割
const HeavyChart = lazy(() => import('./components/HeavyChart'));

缓存策略

// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          router: ['react-router-dom'],
          ui: ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu'],
        },
      },
    },
  },
});

健康检查 & 监控

健康检查端点

// 适用于 Docker/Kubernetes
// api/health.ts (Next.js)
export async function GET() {
  return Response.json({ status: 'healthy', timestamp: Date.now() });
}

错误跟踪 (Sentry)

// sentry.client.config.ts
import * as Sentry from '@sentry/react';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1,
});

// 包装应用
const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes);

常见问题

问题 解决方案
刷新时出现404(SPA) 为 SPA 回退配置服务器
环境变量未定义 检查前缀(VITE_, NEXT_PUBLIC_)
CI上构建失败 检查 Node 版本,清除缓存
Docker 镜像过大 使用多阶段构建,alpine 基础
构建缓慢 启用缓存,平行化

部署清单

部署到生产环境前:

  • [ ] 设置环境变量
  • [ ] 本地构建成功
  • [ ] 测试通过
  • [ ] 配置安全头信息
  • [ ] 启用错误跟踪
  • [ ] 性能优化(捆绑大小,代码分割)
  • [ ] SEO 元标签(如适用)
  • [ ] 启用 SSL/HTTPS
  • [ ] 配置自定义域名
  • [ ] 健康检查端点工作正常