You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt/Vue应用部署GitHub Pages与Route53异常求助

问题描述
  • 已解决GitHub Pages默认显示README的问题,当前可正常展示index文件,但Express服务器接口返回404,该情况切换GitHub Actions工作流后出现。
  • 部署的是包含客户端与Express服务端代码的Nuxt Vue应用,本地运行完全正常,但部署至Route53时出现502 Bad Gateway错误。10个月前曾成功部署到GitHub Pages和Route53,现在无法正常运行,寻求排查建议。

相关配置文件

GitHub Actions工作流

# Sample workflow for building and deploying a Nuxt site to GitHub Pages
#
# To get started with Nuxt see: https://nuxtjs.org/docs/get-started/installation
#
name: Deploy Nuxt site to Pages

on:
  # Runs on pushes targeting the default branch
  push:
    branches: ["main"]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow one concurrent deployment
concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Detect package manager
        id: detect-package-manager
        run: |
          if [ -f "${{ github.workspace }}/yarn.lock" ]; then
            echo "manager=yarn" >> $GITHUB_OUTPUT
            echo "command=install" >> $GITHUB_OUTPUT
            exit 0
          elif [ -f "${{ github.workspace }}/package.json" ]; then
            echo "manager=npm" >> $GITHUB_OUTPUT
            echo "command=ci" >> $GITHUB_OUTPUT
            exit 0
          else
            echo "Unable to determine packager manager"
            exit 1
          fi
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: "16"
          cache: ${{ steps.detect-package-manager.outputs.manager }}
      - name: Setup Pages
        uses: actions/configure-pages@v2
        with:
          # Automatically inject router.base in your Nuxt configuration file and set
          # target to static (https://nuxtjs.org/docs/configuration-glossary/configuration-target/).
          #
          # You may remove this line if you want to manage the configuration yourself.
          static_site_generator: nuxt
      - name: Restore cache
        uses: actions/cache@v3
        with:
          path: |
            dist
            .nuxt
          key: ${{ runner.os }}-nuxt-build-${{ hashFiles('dist') }}
          restore-keys: |
            ${{ runner.os }}-nuxt-build-
      - name: Install dependencies
        run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
      - name: Static HTML export with Nuxt
        run: ${{ steps.detect-package-manager.outputs.manager }} run generate
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v1
        with:
          path: ./dist

  # Deployment job
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v1

package.json脚本

"scripts": {
    "dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
    "build": "nuxt --openssl-legacy-provider build",
    "generate": "nuxt generate",
    "start": "cross-env NODE_ENV=production node server/index.js",
  },

server/index.js

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
}
const Post = require('./models/post');
const express = require('express');
const consola = require('consola');
const { Nuxt, Builder } = require('nuxt');
const app = express();
const mongoose = require('mongoose');
const xss = require('xss-clean');


app.use(
    express.urlencoded({
      extended: true
    })
  )
app.use(express.json())
app.use(xss());

// Import and set Nuxt.js options
const config = require('../nuxt.config.js');
config.dev = process.env.NODE_ENV !== 'production';

// Init Nuxt.js
const nuxt = new Nuxt(config);
const { host, port } = nuxt.options.server;

const username = process.env.username;
const pwd = process.env.pwd;
const server = process.env.server;
const db = process.env.db;

const dbURI = `mongodb+srv://${username}:${pwd}@${server}/${db}?retryWrites=true&w=majority`;

async function start() {
    // Build only in dev mode
    if (config.dev) {
        const builder = new Builder(nuxt);
       await builder.build();
    } else {
        await nuxt.ready();
    }
    // Render every route with Nuxt.js
    app.use(nuxt.render);

    consola.ready({
        message: `Server listening on http://${host}:${port}`,
        badge: true
    });
}

start();

mongoose
    .connect(dbURI, {useNewUrlParser: true, useUnifiedTopology: true})
    .then((result) => {
        app.listen(port, host); // listen
        }
    )
    .catch(err => console.log(err));

app.get('/isAlive', async (req, res) => {
    res.send('i am alive');
});

app.get('/posts', (req, res) => {
    Post
        .find()
        .sort({createdAt: -1})
        .then((result) => {
            res.send(result);
        })
        .catch((err) => console.log(err));
})

app.post(
    '/posts', 
    (req, res) => {
        const post = new Post({
            body: req.body.post.trim()
        });
        post
            .save()
            .then((result) => {
                res.send(result);
            })
            .catch((err) => console.log(err));
    }
);

nuxt.config.js

// import colors from 'vuetify/es5/util/colors'

module.exports = {
  // Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
  ssr: false,
  telemetry: false,

  // Target: https://go.nuxtjs.dev/config-target
  target: 'static',

  // Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    titleTemplate: '%s',
    title: '',
    htmlAttrs: {
      lang: 'en'
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

  // Global CSS: https://go.nuxtjs.dev/config-css
  css: [
  ],

  // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
  plugins: [
  ],

  // Auto import components: https://go.nuxtjs.dev/config-components
  components: true,

  // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
  buildModules: [
    // https://go.nuxtjs.dev/typescript
    '@nuxtjs/typescript-build',
    // https://go.nuxtjs.dev/vuetify
    '@nuxtjs/vuetify',
  ],

  // Modules: https://go.nuxtjs.dev/config-modules
  modules: ['@nuxtjs/axios'
  ],
  axios: {
    baseURL: '/'
  },

  // Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
  vuetify: {
    customVariables: ['~/assets/variables.scss'],
    theme: {
      dark: false
    }
  },

  // Build Configuration: https://go.nuxtjs.dev/config-build
  build: {
    loaders: {
      vue: {
        transformAssetUrls: {
          audio: 'src'
        }
      }
    },
    extend(config, ctx) {
      config.module.rules.push({
        test: /\.(ogg|mp3|wav|mpe?g)$/i,
        loader: 'file-loader',
        options: {
          name: '[path][name].[ext]',
          esModule: false
        }
      })
    }
  }
}

补充说明

推送至main分支会触发构建,此前曾提交.nuxt与dist文件夹,但部署后仍出现上述问题。


排查建议

针对GitHub Pages接口404问题

  1. GitHub Pages仅支持静态文件托管,无法运行Node.js/Express服务。当前工作流用nuxt generate生成静态文件部署,而你的Express接口属于服务端代码,静态环境不会启动这些接口,这是核心原因。之前成功部署可能是用了支持Node服务的平台,或是当时工作流并非仅部署静态文件。
  2. 调整接口部署方式:将Express后端迁移到独立的服务托管平台(如Vercel、AWS EC2/Elastic Beanstalk等),修改前端axios的baseURL指向新的后端地址,确保前端请求能正确到达运行中的服务。

针对Route53 502 Bad Gateway问题

  1. 检查Route53解析配置:确认域名解析的目标地址是否正确,是否指向了运行后端服务的实例/负载均衡器。如果之前是静态前端+独立后端的部署模式,需确认后端服务是否正常运行。
  2. 后端服务状态排查:
    • 若后端部署在AWS,检查EC2实例是否正常启动,安全组是否开放了服务端口(默认是nuxt配置的端口),是否能通过公网IP直接访问接口。
    • 查看后端服务日志,排查是否存在环境变量缺失、依赖安装失败、MongoDB连接错误等导致服务启动失败的问题。
  3. 工作流完整性检查:当前GitHub Actions仅处理了前端静态文件的部署,未涉及后端服务的部署。如果之前的部署是同时更新前后端,需调整工作流或单独部署后端服务,确保Route53指向的后端是最新且运行正常的版本。
  4. Nuxt配置适配:你的nuxt.config.js设置了ssr: false和target: 'static',属于纯静态模式,但代码中包含Express服务逻辑。若需要运行后端接口,应将ssr设为true、target设为server,并部署到支持Node服务的平台,而非GitHub Pages。
  5. 数据库连接验证:确认生产环境的MongoDB连接参数(环境变量)是否正确配置,后端服务是否有权限访问MongoDB集群,数据库连接失败会导致服务无法正常启动,进而引发502错误。

内容的提问来源于stack exchange,提问作者fumeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:20:27