本地可运行PERN栈Todo应用部署Azure Web App后运行异常
该故障和node_modules缺失无关,Azure App Service部署流程会自动执行依赖安装,核心问题是目录结构适配缺失、启动配置错误、前后端托管逻辑未对齐云环境要求:
- 项目采用client、server分目录的前后端分离结构,仓库根目录无统一的构建、启动配置,Azure默认仅在仓库根目录识别package.json执行命令,无法感知子目录下的前后端代码
- 未配置Azure侧适配的启动命令,服务端启动入口无法被定位,直接触发进程退出报错
- 服务端未配置React静态资源托管规则,即便服务启动成功,前端页面、路由也会返回404
- 若服务端写死了本地监听端口、本地数据库连接地址,也会在Azure环境触发连接失败
1. 新增根目录配置适配Azure部署逻辑
在仓库根目录(与client、server文件夹同级)新建package.json文件,写入如下配置,让Azure可以按顺序执行前后端依赖安装、前端构建、服务端启动流程:
{ "name": "pern-todo", "version": "1.0.0", "scripts": { "install:client": "cd client && npm install", "install:server": "cd server && npm install", "build:client": "cd client && npm run build", "postinstall": "npm run install:client && npm run install:server", "build": "npm run build:client", "start": "cd server && node index.js" }, "engines": { "node": "18.x" } }
配置里的node版本替换为你本地开发使用的LTS版本即可,避免非LTS版本带来的兼容问题
2. 修改服务端逻辑适配生产环境
打开服务端入口文件(默认路径为server/index.js),在所有业务接口路由定义之前,新增静态资源托管和前端路由兜底逻辑,让Express可以直接返回React打包后的页面内容:
const path = require('path'); // 托管React构建产物 app.use(express.static(path.join(__dirname, '../client/build'))); // 前端路由兜底,所有非API请求返回React入口文件 app.get('*', (req, res) => { res.sendFile(path.join(__dirname, '../client/build/index.html')); });
同时修改服务端端口监听逻辑,适配Azure自动分配的端口环境变量,不要写死本地开发用的端口:
// 优先使用Azure注入的PORT环境变量,本地开发 fallback 到你常用的后端端口 const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
另外检查数据库连接配置,不要硬编码本地数据库地址,将生产环境数据库连接串配置在Azure Web App的「配置-应用程序设置」中,代码侧通过process.env读取即可。
3. 配置Azure侧启动参数
进入Azure Portal对应Web App的管理页,打开「配置-常规设置」,将启动命令设置为npm start,保存配置。
4. 排查部署过滤规则
检查仓库根目录的.gitignore文件,不要提交node_modules文件夹到仓库(Azure会自动安装依赖,提交本地依赖反而会触发权限、版本兼容问题),同时不要误将client目录下的构建脚本、server目录的业务文件加入忽略列表。
所有修改提交到关联的GitHub分支后,重新触发部署,部署完成后打开Azure门户的「日志流」面板,看到服务端端口监听成功的日志输出后,直接访问站点域名即可正常使用。
内容的提问来源于stack exchange,提问作者Luis

