Heroku本地运行Node.js+React项目正常,部署后仅显示index.html报错如何解决
1. 修复路径拼接语法错误
你的app.js中静态文件返回的路径拼接写法有误,path.join需使用逗号分隔参数而非加号,该问题在本地文件系统可能碰巧生效,但Heroku的容器文件路径规则会导致拼接结果异常,最终React打包生成的JS/CSS等静态资源加载失败,仅显示HTML骨架:
// 错误写法 res.sendFile(path.join(__dirname+'/frontend/build/index.html')); // 正确写法 res.sendFile(path.join(__dirname, './frontend/build/index.html'));
2. 替换非LTS版本的Node.js运行环境
你指定的Node.js 15.4.0属于非长期支持版本,Heroku对非LTS版本的兼容性支持不完善,极易出现运行时异常,建议将后端package.json的engines字段替换为稳定的LTS版本:
"engines": { "node": "16.x", "npm": "8.x" }
3. 修复前端依赖安装失败问题
你使用的npm 7+版本默认开启peer依赖严格校验,很容易导致前端依赖安装中断,最终heroku-postbuild执行失败、没有生成正确的build目录。修改后端package.json的heroku-postbuild字段,跳过peer依赖校验:
"heroku-postbuild": "cd frontend && npm install --legacy-peer-deps && npm run build"
同时确认你的项目目录结构符合预期:根目录存放后端package.json,frontend文件夹与后端package.json同级,避免cd frontend执行失败。
4. 确认服务监听逻辑正确
你提供的app.js代码片段缺少app.listen逻辑,若该逻辑缺失或者位置错误,会导致Node服务没有正确绑定端口,Heroku检测不到服务启动成功就会发送SIGTERM信号终止进程,抛出143退出码。请确保在所有路由、中间件配置完成后,添加如下监听逻辑:
app.listen(PORT, () => { console.log(`服务运行在端口${PORT}`); })
5. 修正生产环境API请求逻辑
前端package.json中的proxy配置仅对react-scripts start启动的本地开发服务器生效,部署到Heroku后该配置不生效,如果你的前端请求写死了http://localhost:5000前缀,会导致所有接口请求失败。请将前端所有API请求修改为相对路径,无需加域名前缀。
内容的提问来源于stack exchange,提问作者Mert Karagöz

