前端搭建 CI/CD 工作流指南

1. 选择 CI/CD 工具

常见的前端 CI/CD 工具选择:

  • GitHub Actions (与 GitHub 深度集成)
  • GitLab CI/CD (与 GitLab 深度集成)
  • Jenkins (自托管,高度可定制)
  • CircleCI (云服务)
  • Travis CI (云服务)

2. 基础 CI/CD 流程设计

典型的前端 CI/CD 流程包括以下阶段:

  1. 代码提交 → 2. 自动构建 → 3. 代码检查 → 4. 自动化测试 → 5. 部署

3. 使用 GitHub Actions 示例

一、前期准备

  1. 项目要求

    • 代码托管在 GitHub 仓库
    • 项目根目录有 package.json 文件
    • 有基本的构建脚本 (如 npm run build)
  2. 环境准备

    • 在项目根目录创建 .github/workflows 文件夹
    • 准备部署目标的相关凭据 (如需)

二、基础 CI/CD 配置文件

创建 .github/workflows/main.yml 文件:

yaml 复制代码
name: Frontend CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]  # 监听 main 和 develop 分支的推送
  pull_request:
    branches: [ main ]          # PR 到 main 分支时触发

env:
  NODE_VERSION: '18.x'          # 统一 Node.js 版本

jobs:
  # 第一个 job:代码检查和测试
  lint-and-test:
    name: Lint & Test
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3   # 检出代码
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'            # 启用 npm 缓存
    
    - name: Install dependencies
      run: npm ci               # 使用 ci 而不是 install 保证依赖一致
    
    - name: Run ESLint
      run: npm run lint
    
    - name: Run unit tests
      run: npm test
    
    - name: Upload test coverage
      uses: codecov/codecov-action@v3
      with:
        token: ${{ secrets.CODECOV_TOKEN }}  # 可选:上传测试覆盖率到 Codecov

  # 第二个 job:构建和部署
  build-and-deploy:
    name: Build & Deploy
    needs: lint-and-test        # 依赖 lint-and-test 成功
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: ${{ env.NODE_VERSION }}
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build project
      run: npm run build
      
    - name: Archive production artifacts
      uses: actions/upload-artifact@v3
      with:
        name: build-artifacts
        path: dist/             # 假设构建输出在 dist 目录
        
    - name: Deploy to Staging
      if: github.ref == 'refs/heads/develop'
      run: npm run deploy:staging
      env:
        DEPLOY_TOKEN: ${{ secrets.STAGING_DEPLOY_TOKEN }}
    
    - name: Deploy to Production
      if: github.ref == 'refs/heads/main'
      run: npm run deploy:production
      env:
        DEPLOY_TOKEN: ${{ secrets.PROD_DEPLOY_TOKEN }}

三、详细配置说明

1. 触发条件 (on)

yaml 复制代码
on:
  push:
    branches: [ main, develop ]  # 指定触发分支
    tags: [ 'v*' ]              # 可选:标签推送触发
  pull_request:
    branches: [ main ]          # PR 到 main 时触发
  schedule:                     # 可选:定时触发
    - cron: '0 0 * * *'         # 每天 UTC 午夜

2. 环境变量管理

yaml 复制代码
env:
  NODE_VERSION: '18.x'
  BUILD_DIR: 'dist'
  
jobs:
  deploy:
    env:
      API_BASE_URL: ${{ secrets.API_BASE_URL }}

3. 矩阵构建 (多环境测试)

yaml 复制代码
jobs:
  test:
    strategy:
      matrix:
        node-version: ['16.x', '18.x', '20.x']
        os: [ubuntu-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}

4. 缓存优化

yaml 复制代码
- name: Cache node modules
  uses: actions/cache@v3
  id: cache
  with:
    path: |
      node_modules
      .next/cache
    key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}

5. 人工审核 (生产部署)

yaml 复制代码
- name: Wait for manual approval
  uses: trstringer/manual-approval@v1
  with:
    secret: ${{ github.token }}
    approvers: 'team-lead,product-owner'
    minimum-approvals: 1

四、部署到不同平台的配置示例

1. 部署到 GitHub Pages

yaml 复制代码
- name: Deploy to GitHub Pages
  uses: peaceiris/actions-gh-pages@v3
  with:
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: ./dist
    keep_files: true            # 保留历史文件

2. 部署到 AWS S3 + CloudFront

yaml 复制代码
- name: Configure AWS Credentials
  uses: aws-actions/configure-aws-credentials@v2
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: us-east-1

- name: Deploy to S3
  run: |
    aws s3 sync ./dist s3://your-bucket-name --delete
    aws cloudfront create-invalidation \
      --distribution-id ${{ secrets.CF_DISTRIBUTION_ID }} \
      --paths "/*"

3. 部署到 Vercel

yaml 复制代码
- name: Install Vercel CLI
  run: npm install -g vercel@latest

- name: Deploy to Vercel
  run: vercel --prod --token ${{ secrets.VERCEL_TOKEN }}
  env:
    VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
    VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

五、完整高级示例

yaml 复制代码
name: Advanced Frontend CI/CD

on:
  push:
    branches: [ main, develop ]
    tags: [ 'v*' ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:    # 允许手动触发
    inputs:
      environment:
        description: 'Deploy environment'
        required: true
        default: 'staging'
        type: choice
        options:
        - staging
        - production

env:
  NODE_VERSION: '18.x'
  BUILD_DIR: 'dist'

jobs:
  setup:
    runs-on: ubuntu-latest
    outputs:
      should_deploy: ${{ steps.check-ref.outputs.should_deploy }}
    steps:
    - name: Check branch/tag
      id: check-ref
      run: |
        if [[ $GITHUB_REF == refs/heads/main || $GITHUB_REF == refs/heads/develop || $GITHUB_REF == refs/tags/v* ]]; then
          echo "should_deploy=true" >> $GITHUB_OUTPUT
        else
          echo "should_deploy=false" >> $GITHUB_OUTPUT
        fi

  lint-test:
    needs: setup
    if: ${{ needs.setup.outputs.should_deploy == 'true' }}
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: ${{ env.NODE_VERSION }}
    
    - name: Cache dependencies
      uses: actions/cache@v3
      with:
        path: node_modules
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run linter
      run: npm run lint
    
    - name: Run tests
      run: npm test -- --coverage
    
    - name: Upload coverage
      uses: codecov/codecov-action@v3

  build:
    needs: lint-test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: ${{ env.NODE_VERSION }}
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build project
      run: npm run build
    
    - name: Upload artifacts
      uses: actions/upload-artifact@v3
      with:
        name: build-output
        path: ${{ env.BUILD_DIR }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment: 
      name: ${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'production') || 'staging' }}
      url: ${{ steps.deploy.outputs.deployment_url }}
    steps:
    - name: Download artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-output
        path: ${{ env.BUILD_DIR }}
    
    - name: Deploy to environment
      id: deploy
      run: |
        if [ "${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'production') || 'staging' }}" == "production" ]; then
          npm run deploy:production
          echo "deployment_url=https://production.example.com" >> $GITHUB_OUTPUT
        else
          npm run deploy:staging
          echo "deployment_url=https://staging.example.com" >> $GITHUB_OUTPUT
        fi

六、最佳实践建议

  1. 分阶段执行:将流程分为 lint/test/build/deploy 等独立阶段

  2. 失败快速:将最容易失败的步骤放在前面

  3. 缓存优化:缓存 node_modules 和构建缓存

  4. 环境隔离:严格区分 staging 和 production 环境

  5. 安全防护

    • 使用 GitHub Secrets 存储敏感信息
    • 生产部署添加人工审批
  6. 监控通知

    • 集成 Slack/Teams 通知
    • 失败时自动通知相关人员
  7. 定期清理:设置 artifacts 和 cache 的保留策略

通过以上配置,你可以建立一个健壮、高效的前端 CI/CD 流程,实现从代码提交到自动化部署的完整链路。

相关推荐
去旅行、在路上23 分钟前
chrome使用手机调试触屏web
前端·chrome
Aphasia3111 小时前
模式验证库——zod
前端·react.js
lexiangqicheng1 小时前
es6+和css3新增的特性有哪些
前端·es6·css3
拉不动的猪2 小时前
都25年啦,还有谁分不清双向绑定原理,响应式原理、v-model实现原理
前端·javascript·vue.js
烛阴2 小时前
Python枚举类Enum超详细入门与进阶全攻略
前端·python
孟孟~2 小时前
npm run dev 报错:Error: error:0308010C:digital envelope routines::unsupported
前端·npm·node.js
孟孟~3 小时前
npm install 报错:npm error: ...node_modules\deasync npm error command failed
前端·npm·node.js
狂炫一碗大米饭3 小时前
一文打通TypeScript 泛型
前端·javascript·typescript
wh_xia_jun3 小时前
在 Spring Boot 中使用 JSP
java·前端·spring boot
二十雨辰3 小时前
[HTML5]快速掌握canvas
前端·html