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

Next.js部署至Azure Web App后出现渲染及模块缺失问题

问题描述

通过GitHub Actions将Next.js PWA部署到Azure Web App,CI/CD流水线运行成功,但访问已部署应用时遇到渲染错误。App Service日志流显示以下错误:

2024-10-13T16:07:14.538332001Z     at Module._resolveFilename (node:internal/modules/cjs/loader:1145:15)
2024-10-13T16:07:14.538351203Z     at Module._load (node:internal/modules/cjs/loader:986:27)
2024-10-13T16:07:14.538357203Z     at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)
2024-10-13T16:07:14.538363004Z     at node:internal/main/run_main_module:28:49 {
2024-10-13T16:07:14.538368704Z   code: 'MODULE_NOT_FOUND',
2024-10-13T16:07:14.538374204Z   requireStack: []
2024-10-13T16:07:14.538379905Z }

相关配置文件如下:

next.config.js

const withPWA = require('next-pwa')({
    dest: 'public',
    disable: process.env.NODE_ENV === 'development'
    // add your own icons to src/app/manifest.ts
    // to re-generate manifest.json, you can visit https://tomitm.github.io/appmanifest/
});

/** @type {import('next').NextConfig} */
module.exports = withPWA({
    output: "standalone",
    swcMinify: true,
    reactStrictMode: true,
    eslint: {
        dirs: ['src']
    }
});

GitHub Actions工作流配置

name: Deploy Next.js to Azure Web App

on:
  workflow_dispatch:

env:
  NODE_VERSION: 20
  NEXT_APP_DIR: src/FinPhlo.Web

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ${{ env.NEXT_APP_DIR }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Detect package manager
        id: detect-package-manager
        run: |
          if [ -f "yarn.lock" ]; then
            echo "manager=yarn" >> $GITHUB_OUTPUT
            echo "command=install" >> $GITHUB_OUTPUT
            echo "runner=yarn" >> $GITHUB_OUTPUT
          elif [ -f "package.json" ]; then
            echo "manager=npm" >> $GITHUB_OUTPUT
            echo "command=ci" >> $GITHUB_OUTPUT
            echo "runner=npx --no-install" >> $GITHUB_OUTPUT
          else
            echo "Unable to determine package manager"
            exit 1
          fi

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: ${{ steps.detect-package-manager.outputs.manager }}
          cache-dependency-path: ${{ env.NEXT_APP_DIR }}/package-lock.json

      - name: Restore cache
        uses: actions/cache@v4
        with:
          path: |
            ${{ env.NEXT_APP_DIR }}/.next/cache
          key: ${{ runner.os }}-nextjs-${{ hashFiles('${{ env.NEXT_APP_DIR }}/package-lock.json') }}-${{ hashFiles('${{ env.NEXT_APP_DIR }}/**.[jt]s', '${{ env.NEXT_APP_DIR }}/**.[jt]sx') }}
          restore-keys: |
            ${{ runner.os }}-nextjs-${{ hashFiles('${{ env.NEXT_APP_DIR }}/package-lock.json') }}-

      - name: Install dependencies
        run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}

      - name: Build with Next.js
        run: ${{ steps.detect-package-manager.outputs.runner }} next build --no-lint

      - name: Zip artifact for deployment
        run: zip ../../web.zip ./* .next -qr

      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: web-app
          path: web.zip
          retention-days: 30

  deploy-testing:
    environment:
      name: Testing
      url: ${{ steps.deployment.outputs.webapp-url }}
    runs-on: ubuntu-latest
    needs: build
    permissions:
      id-token: write
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v3
        with:
          name: web-app

      - name: Azure login
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Deploy to Testing
        id: deployment
        uses: azure/webapps-deploy@v3
        with:
          app-name: finphlo-testing-frontend-app
          package: web.zip

Terraform配置

module "frontend_linux_web_app" {
  source = "../../modules/web-app/linux-web-app"

  basename            = "${local.basename}-frontend"
  resource_group_name = var.resource_group_name
  location            = var.location
  service_plan_id     = data.azurerm_service_plan.linux_uk_south_asp.id

  site_config = {
    always_on           = true
    minimum_tls_version = "1.2"
    ftps_state          = "Disabled"
    http2_enabled       = true
    app_command_line    = "node .next/standalone/server.js"
    application_stack = {
      node = {
        node_version = "20-lts"
      }
    }
  }

  https_only = true

  identity_type = "SystemAssigned"

  tags = var.tags
}

package.json

{
    "name": "fin-phlo",
    "version": "0.1.0",
    "private": true,
    "author": "phlo",
    "scripts": {
        "dev": "next dev",
        "build": "next build",
        "turbo": "npx turbo@2.0.9",
        "build:turbo": "npm run turbo run build",
        "postbuild": "next-sitemap --config next-sitemap.config.js",
        "start": "next start",
        "type-check": "tsc --noEmit",
        "check:turbo": "npm run turbo lint type-check",
        "format": "prettier --write src",
        "up-interactive": "npx npm-check-updates -i",
        "up-latest": "npx npm-check-updates -u --interactive --latest",
        "release": "cross-env HUSKY=0 standard-version",
        "push-release": "git push --follow-tags origin main",
        "prepare": "husky",
        "sanity-check": "npm run checkTs && npm run lint && npm run prettier:check",
        "checkTs": "tsc && tsc-strict",
        "eslint": "eslint --ext js,ts,tsx",
        "lint": "npm run eslint -- src",
        "lint:fix": "npm run eslint -- --fix src",
        "prettier:check": "prettier --check .",
        "prettify": "prettier --write --ignore-unknown ."
    },
    "dependencies": {
        "@chakra-ui/icons": "^2.2.3",
        "@chakra-ui/next-js": "^2.2.0",
        "@chakra-ui/react": "^2.8.2",
        "@emotion/react": "^11.13.3",
        "@emotion/styled": "^11.13.0",
        "@hookform/resolvers": "^3.9.0",
        "@types/yup": "^0.32.0",
        "framer-motion": "^11.5.4",
        "next": "^14.2.9",
        "next-auth": "^4.24.8",
        "next-pwa": "^5.6.0",
        "react": "^18.3.1",
        "react-dom": "^18.3.1",
        "react-hook-form": "^7.53.0",
        "react-icons": "^5.3.0",
        "yup": "^1.4.0"
    },
    "devDependencies": {
        "@commitlint/cli": "^19.4.1",
        "@commitlint/config-conventional": "19.4.1",
        "@commitlint/cz-commitlint": "19.4.0",
        "@types/react": "^18.3.5",
        "@typescript-eslint/eslint-plugin": "^8.7.0",
        "commitizen": "^4.3.0",
        "cross-env": "^7.0.3",
        "eslint": "^8.57.0",
        "eslint-config-next": "^14.2.9",
        "eslint-config-prettier": "^9.1.0",
        "eslint-config-sznm": "^2.0.3",
        "husky": "^9.1.5",
        "lint-staged": "^15.2.10",
        "next-sitemap": "^4.2.3",
        "prettier": "^3.3.3",
        "standard-version": "^9.5.0",
        "ts-node": "^10.9.2",
        "typescript": "^5.6.2",
        "typescript-strict-plugin": "^2.4.4"
    },
    "engines": {
        "node": ">=20.14.x",
        "npm": ">=9"
    },
    "packageManager": "npm@9.1.2"
}
解决方案

这个MODULE_NOT_FOUND错误是因为Next.js standalone模式下的部署包不完整,加上启动命令路径错误导致的,具体修复步骤如下:

1. 修正部署包的压缩范围

Next.js output: "standalone" 构建后,会生成.next/standalone目录,这个目录包含了运行所需的所有依赖和服务器文件,当前压缩命令的范围和路径结构不符合要求。

修改GitHub Actions中的Zip artifact for deployment步骤:

- name: Zip artifact for deployment
  run: |
    # 复制standalone目录及必要资源到统一结构
    cp -r .next/standalone ../../
    cp -r .next/static ../../standalone/.next/
    cp -r public ../../standalone/
    cp package.json ../../standalone/
    # 进入standalone目录压缩,确保启动路径正确
    cd ../../standalone
    zip -r ../web.zip ./* -q

2. 修正Azure启动命令

当前Terraform中的启动命令路径错误,部署后standalone是应用根目录,正确的启动路径应为node server.js。

修改Terraform的app_command_line:

app_command_line    = "node server.js"

3. 优化依赖安装(可选)

为减少部署包体积并确保生产依赖完整,可在安装依赖后添加清理dev依赖的步骤:
在GitHub Actions的Install dependencies步骤后添加:

- name: Prune dev dependencies
  run: npm prune --production

4. 验证PWA资源路径

next-pwa生成的Service Worker和manifest文件依赖public目录,第一步的压缩命令已包含该目录,确保部署后这些资源可正常访问。

完成以上修改后,重新运行CI/CD流水线,部署后应用即可正常启动。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:17:01