第二十一章:CI/CD 最佳实践

第二十一章:CI/CD 最佳实践

21.1 CI/CD 概览

核心流程

复制代码
代码提交 → 测试 → 构建 → 部署 → 验证

主流平台

  • GitHub Actions
  • GitLab CI
  • Jenkins
  • CircleCI
  • 阿里云效

21.2 GitHub Actions 配置

基础工作流

yaml 复制代码
# .github/workflows/ci.yml
name: CI/CD

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

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [18, 20]
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run lint
        run: npm run lint
      
      - name: Run type check
        run: npm run type-check
      
      - name: Run unit tests
        run: npm run test:unit
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage/lcov.info

  build:
    needs: test
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build
        run: npm run build
        env:
          VITE_API_URL: ${{ secrets.VITE_API_URL }}
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: dist
          path: dist/

部署到 GitHub Pages

yaml 复制代码
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build
        run: npm run build
        env:
          VITE_BASE_URL: '/your-repo-name/'
      
      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist

部署到 Vercel

yaml 复制代码
name: Deploy to Vercel

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Install Vercel CLI
        run: npm install --global vercel
      
      - name: Deploy to Vercel
        run: vercel --prod --token=${{ secrets.VERCEL_TOKEN }}

21.3 GitLab CI 配置

yaml 复制代码
# .gitlab-ci.yml
image: node:18

stages:
  - test
  - build
  - deploy

variables:
  npm_config_cache: '$CI_PROJECT_DIR/.npm'

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .npm/
    - node_modules/

.test_template: &test
  stage: test
  script:
    - npm ci --cache .npm --prefer-offline
    - npm run lint
    - npm run type-check
    - npm run test:unit
  artifacts:
    reports:
      junit:
        - junit.xml
    paths:
      - coverage/

unit-test:
  <<: *test

build:
  stage: build
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
  only:
    - main
    - develop

deploy_staging:
  stage: deploy
  script:
    - apt-get update -qq && apt-get install -y -qq sshpass
    - sshpass -p $SSH_PASSWORD scp -r dist/* user@staging-server:/var/www/html/
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

deploy_production:
  stage: deploy
  script:
    - apt-get update -qq && apt-get install -y -qq sshpass
    - sshpass -p $SSH_PASSWORD scp -r dist/* user@prod-server:/var/www/html/
  environment:
    name: production
    url: https://example.com
  only:
    - main
  when: manual

21.4 缓存策略优化

依赖缓存

yaml 复制代码
# GitHub Actions 缓存配置
- name: Cache dependencies
  uses: actions/cache@v3
  with:
    path: |
      node_modules
      ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Vite 构建缓存

javascript 复制代码
// vite.config.js
export default defineConfig({
  build: {
    // 启用构建缓存
    cacheDir: 'node_modules/.vite',
    
    // 利用 CI 环境变量
    sourcemap: process.env.CI === 'true'
  }
})

并行构建

yaml 复制代码
# 并行执行多个任务
jobs:
  test:
    strategy:
      matrix:
        task: [lint, type-check, test:unit, test:e2e]
    steps:
      - name: Run ${{ matrix.task }}
        run: npm run ${{ matrix.task }}

21.5 环境变量管理

Secrets 配置

yaml 复制代码
# GitHub Actions
env:
  VITE_API_URL: ${{ secrets.VITE_API_URL }}
  VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }}

# GitLab CI
variables:
  VITE_API_URL: $VITE_API_URL
  VITE_SENTRY_DSN: $VITE_SENTRY_DSN

多环境配置

javascript 复制代码
// 根据 CI 环境变量动态加载
const env = process.env.CI_ENVIRONMENT_NAME || 'development'

const envConfig = {
  development: {
    VITE_API_URL: 'http://localhost:3000'
  },
  staging: {
    VITE_API_URL: 'https://staging-api.example.com'
  },
  production: {
    VITE_API_URL: 'https://api.example.com'
  }
}

21.6 测试优化

并行测试

yaml 复制代码
# 使用 vitest 并行测试
- name: Run tests
  run: npm run test:unit -- --reporter=default --run --pool=forks

E2E 测试

yaml 复制代码
# Playwright E2E 测试
- name: Install Playwright
  run: npx playwright install --with-deps chromium

- name: Build for E2E
  run: npm run build

- name: Run E2E tests
  run: npm run test:e2e

测试报告

yaml 复制代码
# 上传测试报告
- name: Upload test results
  uses: actions/upload-artifact@v3
  with:
    name: test-results
    path: test-results/

21.7 构建优化

增量构建

javascript 复制代码
// 利用缓存加速构建
build: {
  // 只在依赖变化时重新构建
  rollupOptions: {
    cache: true
  }
}

构建大小限制

yaml 复制代码
# 在 CI 中检查构建大小
- name: Check bundle size
  run: |
    SIZE=$(du -sk dist | cut -f1)
    LIMIT=500
    if [ $SIZE -gt $LIMIT ]; then
      echo "❌ Bundle size $SIZE KB exceeds limit $LIMIT KB"
      exit 1
    fi
    echo "✅ Bundle size $SIZE KB within limit"

21.8 部署策略

蓝绿部署

yaml 复制代码
# 示例:切换负载均衡器
- name: Deploy to Blue
  run: rsync -avz dist/ blue-server:/var/www/html/

- name: Switch to Blue
  run: |
    ssh load-balancer "sudo update-lb --set blue"
    sleep 30
    ssh load-balancer "sudo update-lb --health-check"

灰度发布

yaml 复制代码
- name: Canary deployment
  run: |
    # 部署到 10% 的实例
    for i in {1..10}; do
      rsync -avz dist/ canary-$i:/var/www/html/
    done
    
    # 等待验证
    sleep 300
    
    # 全量部署
    for i in {11..100}; do
      rsync -avz dist/ server-$i:/var/www/html/
    done

回滚机制

yaml 复制代码
# 保留历史版本
- name: Archive previous version
  run: |
    tar -czf /backups/vite-app-$(date +%Y%m%d-%H%M%S).tar.gz dist/

- name: Deploy new version
  run: rsync -avz dist/ /var/www/html/

# 回滚脚本
rollback:
  script:
    - LATEST_BACKUP=$(ls -t /backups/vite-app-*.tar.gz | head -1)
    - tar -xzf $LATEST_BACKUP -C /var/www/html/

21.9 监控与告警

健康检查

yaml 复制代码
- name: Health check
  run: |
    curl -f https://example.com/health || exit 1

性能监控集成

yaml 复制代码
- name: Run Lighthouse CI
  run: |
    npm install -g @lhci/cli
    lhci autorun --upload.target=temporary-public-storage

21.10 最佳实践总结

优化清单

  • 依赖管理 :使用 npm ci 而非 npm install
  • 缓存策略:缓存 node_modules 和构建产物
  • 并行执行:独立任务并行运行
  • 环境隔离:不同环境使用不同配置
  • 安全保密:敏感信息使用 Secrets
  • 构建验证:检查构建产物大小和质量
  • 自动化测试:单元测试 + E2E 测试
  • 部署策略:蓝绿部署或灰度发布
  • 回滚能力:保留历史版本,支持快速回滚
  • 监控告警:部署后健康检查和性能监控

常见问题

Q: CI 中构建慢怎么办?

A: 启用缓存、使用并行任务、升级 CI 机器配置

Q: 环境变量如何管理?

A: 使用 CI 平台的 Secrets 功能,不同环境单独配置

Q: 部署失败如何快速回滚?

A: 保留至少 3 个历史版本,准备回滚脚本

Q: 如何确保构建产物一致性?

A: 锁定依赖版本(package-lock.json),使用固定 Node 版本


本章小结

CI/CD 是现代前端工程的基石:

  • 自动化:减少人工操作,提升效率
  • 一致性:确保构建环境一致
  • 可靠性:测试自动化,降低风险
  • 可追溯:每次部署都有记录

根据团队规模和项目复杂度,选择合适的 CI/CD 策略。

相关推荐
心连欣1 小时前
解锁对象遍历:当字符串遇上for...in循环
前端·javascript
Sestid1 小时前
前端Cursor使用指南(后续会更新Claude)
前端·claude·cursor
戴维南1 小时前
LangChain 在 Agent 开发中的定位:10 个模块(含代码对比,耳机售后案例)
前端
ouzz2 小时前
使用纯canvas绘制一个掘金首页
前端·canvas
用户6957584491282 小时前
Vue 3 响应式系统:解构赋值与依赖收集的正确姿势
前端
乐乐同学yorsal2 小时前
一个 TypeScript 写的图片视频处理工具箱,吊打一切付费软件!
前端·命令行
lzhdim2 小时前
SQL 入门 10:SQL 内置函数:数值、字符串与时间处理
前端·数据库·sql
jstopo网站2 小时前
水厂水泵工作流程图canvas动画
前端·javascript
张元清2 小时前
5 分钟用 Vite SSR 搭建一个全栈 React 应用
前端·javascript·面试
空中海2 小时前
6.1 主题与暗色模式
运维·服务器·前端·flutter