Nuxt3 SSG部署Azure Web App后Server API路由返回404排查
问题:Nuxt3 SSG部署到Azure Web App后Server API路由返回404
我通过DevOps流水线将Nuxt3 SSG应用部署到Azure Web App,部署过程无异常,但访问站点时所有Server API路由都返回404错误。排查发现server API路由没有被打包到.output文件夹中,这些404错误来自$fetch调用API路由——应用重定向到/login后,第一个错误出现在login布局的onMounted阶段。
相关配置文件
layouts/login.vue
<script setup> onMounted(async () => { await $fetch(`/api/startup`, { method: 'post' }); }); </script>
nuxt.config.ts
import { copy } from '@nuxt/utils'; export default defineNuxtConfig({ devtools: { enabled: process.env.NODE_ENV !== 'production', timeline: { enabled: process.env.NODE_ENV !== 'production' } }, ssr: false, modules: [ [ '@pinia/nuxt', { autoImports: ['defineStore', 'acceptHMRUpdate', 'storeToRefs'] } ], '@nuxtjs/tailwindcss', '@nuxtjs/color-mode' ], css: [ '@/assets/css/main.css' ], hooks: { generate: { after: async () => { await copy('server', '.output/public/server'); // 尝试复制server文件夹到.output } }, }, app: { baseURL: '/', buildAssetsDir: '.output' }, runtimeConfig: { // 省略配置 } })
azure-pipelines.yaml
trigger: - sandbox pool: vmImage: ubuntu-latest steps: - task: NodeTool@0 inputs: versionSpec: '18.x' displayName: '安装Node.js' - script: | npm install displayName: '安装依赖' - script: | npm run generate displayName: '生成静态站点' - task: AzureWebApp@1 inputs: azureSubscription: 'secret-string' appType: webApp appName: 'secret-app-name' slotName: 'development' package: '.output/public' deploymentMethod: 'runFromPackage' displayName: '部署到Azure Web App'
web.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <defaultDocument> <files> <clear /> <add value="public/index.html" /> </files> </defaultDocument> <directoryBrowse enabled="false" /> <rewrite> <rules> <rule name="Handle History Mode and custom routes" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Rewrite" url="/" /> </rule> </rules> </rewrite> <httpErrors> <remove statusCode="404" subStatusCode="-1" /> <error statusCode="404" path="/404.html" responseMode="ExecuteURL" /> </httpErrors> </system.webServer> </configuration>
部署后的目录结构
流水线运行后,Azure Web App的wwwroot目录结构如下:
/.output /login 200.html 400.html favicon.ico index.html
问题分析与解决步骤
核心问题
- SSG模式不支持Server API路由:Nuxt3的
ssr: false+npm run generate生成的是纯静态站点,Server API路由(server/目录下的文件)属于服务端运行时代码,不会被打包到静态输出中——静态站点根本无法运行服务端API。 - 复制server文件夹无效:即使通过
generate:after钩子把server复制到.output/public,静态Web App也无法解析这些Node.js代码,因为Azure Web App的静态站点模式不会启动Node.js服务。 - 路由重写规则覆盖API请求:
web.config中的重写规则会把所有非文件/非目录的请求重写到/,导致/api/*请求被强制跳转到首页,最终返回404。
解决方法
方案1:切换到Nuxt3服务端部署模式(推荐)
如果必须保留Server API路由,放弃SSG模式,改用服务端部署:
- 修改
nuxt.config.ts:可以保留ssr: true(默认值可直接省略);如果需要客户端渲染但保留服务端API,保持ssr: false但将构建命令从generate改为build。 - 调整流水线脚本:把
npm run generate替换为npm run build。 - 修改Azure部署任务的
package路径:从.output/public改为.outputpackage: '.output' - 确认Azure Web App配置:在Azure门户的应用服务配置中,设置运行时栈为Node.js。
方案2:将API逻辑迁移到客户端
如果API逻辑不需要服务端执行,把server/api下的代码迁移到客户端,或者用静态JSON文件作为数据源,彻底避免依赖服务端API。
方案3:单独部署API到Azure Functions
把Server API路由迁移到Azure Functions,客户端$fetch直接调用Functions的公开URL,实现前后端分离部署。
额外调整:修复web.config重写规则
如果选择方案1,需要修改web.config,确保API请求不被重写规则拦截:
<rewrite> <rules> <!-- 优先处理API请求,不触发SPA重写 --> <rule name="API Routes" stopProcessing="true"> <match url="^api/(.*)" /> <action type="Rewrite" url="api/{R:1}" /> </rule> <!-- 处理SPA历史模式路由 --> <rule name="Handle History Mode" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Rewrite" url="/" /> </rule> </rules> </rewrite>
内容的提问来源于stack exchange,提问作者mojojojo8
相关产品推荐
相关产品推荐

