GitHub Actions自动部署Vue前端到ECS

星期一, 6月 22, 2026 | 3分钟阅读 | 更新于 星期一, 6月 22, 2026

@

本文是部署系列的延续。SSH 密钥配置和 GitHub Secrets 设置与后端篇相同(参考前一篇文章),本文不再重复,重点讲 Vue 前端的自动部署流程。

一、流程回顾

本地 push → GitHub 私有仓库 → GitHub Actions → SSH 连接 ECS → git pull → npm build → 更新 Nginx

前提条件(参考上一篇):

  • ECS 上已配置 SSH 密钥
  • GitHub 仓库已添加 ECS_HOSTECS_USERECS_SSH_KEY 三个 Secrets
  • ECS 上已 clone 前端代码到 /opt/app/myapp-frontend

二、前端 Workflow

创建 .github/workflows/deploy-frontend.yml

name: Deploy Frontend to ECS

on:
  push:
    branches:
      - main
    paths:
      - 'frontend/**'  # 只在前端代码变更时触发

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.ECS_HOST }}
          username: ${{ secrets.ECS_USER }}
          key: ${{ secrets.ECS_SSH_KEY }}
          script: |
            cd /opt/app/myapp-frontend
            git pull origin main
            npm install
            npm run build
            rm -rf /opt/app/frontend/dist
            cp -r dist/ /opt/app/frontend/dist
            nginx -t && systemctl reload nginx
            echo "前端部署完成"

脚本逐行说明

命令作用
git pull origin main拉取最新前端代码
npm install安装/更新依赖
npm run build构建生产版本到 dist/
rm -rf /opt/app/frontend/dist删除旧版本
cp -r dist/ /opt/app/frontend/dist复制新版本
nginx -t && systemctl reload nginx检查配置后平滑重载

注意nginx reload 不会中断现有连接,比 restart 更平滑。

三、前后端合并 Workflow

如果不想维护两个 workflow 文件,可以合并为一个,用 paths-filter 自动判断:

name: Deploy to ECS

on:
  push:
    branches:
      - main

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      backend: ${{ steps.filter.outputs.backend }}
      frontend: ${{ steps.filter.outputs.frontend }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            backend: 'backend/**'
            frontend: 'frontend/**'

  deploy-backend:
    needs: changes
    if: ${{ needs.changes.outputs.backend == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.ECS_HOST }}
          username: ${{ secrets.ECS_USER }}
          key: ${{ secrets.ECS_SSH_KEY }}
          script: |
            cd /opt/app/myapp-backend && git pull origin main
            mvn clean package -DskipTests
            mv target/*.jar /opt/app/myapp.jar
            systemctl restart myapp

  deploy-frontend:
    needs: changes
    if: ${{ needs.changes.outputs.frontend == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.ECS_HOST }}
          username: ${{ secrets.ECS_USER }}
          key: ${{ secrets.ECS_SSH_KEY }}
          script: |
            cd /opt/app/myapp-frontend && git pull origin main
            npm install && npm run build
            rm -rf /opt/app/frontend/dist
            cp -r dist/ /opt/app/frontend/dist
            nginx -t && systemctl reload nginx

优势:只改后端代码时自动跳过前端部署,反之亦然。一个文件管理全部,不用来回切换。

四、前端特殊处理

Nginx 缓存问题

部署新版本后用户可能看到旧页面,因为 Nginx 默认会缓存静态资源。在 Nginx 配置中明确缓存策略:

# index.html 不缓存(确保新版本立即生效)
location = /index.html {
    root /opt/app/frontend/dist;
    add_header Cache-Control "no-cache, no-store, must-revalidate";
}

# JS/CSS 文件名带 hash(Vue 默认),可以长期缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf)$ {
    root /opt/app/frontend/dist;
    expires 30d;
    add_header Cache-Control "public, immutable";
}

构建内存不足

Vue 项目大型时可能 OOM,在 workflow 脚本中改为:

NODE_OPTIONS="--max-old-space-size=4096" npm run build

五、回滚

手动回滚前端:

cd /opt/app/myapp-frontend
git log --oneline -5
git reset --hard <commit>
npm install && npm run build
rm -rf /opt/app/frontend/dist
cp -r dist/ /opt/app/frontend/dist
nginx -t && systemctl reload nginx

六、部署效果

配置完成后,只要 push 前端代码到 main 分支:

  1. GitHub Actions 自动触发
  2. SSH 到 ECS 拉取最新代码
  3. 自动构建并更新 Nginx
  4. 30 秒到 2 分钟完成(取决于项目大小)

不再需要手动 npm run buildscp 上传,真正做到提交即部署。

总结

前端自动部署的核心脚本只有几行:

git pull → npm install → npm run build → 替换 dist → nginx reload

和后端篇配合,整个项目的部署完全自动化。前后端的 CI/CD 模式相同,差别只在构建命令。

© 2026 My Blog

🌱 Powered by Hugo with theme Dream.