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

Heroku部署Node/React应用时所有请求均路由至index.html的问题排查

解决Heroku上Node API路由被React静态文件覆盖的问题

我之前在部署Node+React的SPA应用到Heroku时,也碰到过完全一样的坑——API路由被通配符的index.html接管,哪怕调整了路由顺序也没用。咱们一步步来排查解决:

1. 先确认Heroku真的跑了你的最新代码

你说移除了通配符重定向代码但还是返回index.html,这十有八九是Heroku没拿到你的修改。先做这几步:

  • 确保本地所有代码修改都已经执行 git add . 和 git commit -m "fix: remove wildcard redirect"
  • 重新推送到Heroku:git push heroku main(如果你的默认分支是main,不是master的话)
  • 推送完成后,去Heroku仪表盘的「Deploy」标签看一下最新的部署记录,确认代码已经成功上线

2. 严格核对路由定义的顺序

虽然你说已经把API路由放在前面,但再仔细检查一下代码结构,必须严格遵循这个顺序:

// 第一步:先定义所有API接口路由
app.get('/api/users', UserController.get);
// 其他API路由也要放在这里,比如/app/posts之类的

// 第二步:挂载React静态文件服务
app.use(express.static(path.resolve(__dirname, "./front/build")));

// 第三步:最后放通配符路由,处理React SPA的前端路由
app.get("*", function (request, response) {
  response.sendFile(path.resolve(__dirname, "./front/build", "index.html"));
});

如果你的API路由是拆分到其他文件(比如routes/api.js)的,也要确保app.use('/api', require('./routes/api'))这行代码在静态文件和通配符路由之前。

3. 排查缓存问题

浏览器端缓存

有时候浏览器会缓存旧的响应,哪怕服务器已经改了代码。试试:

  • 用 Ctrl+Shift+R(Windows/Linux)或 Cmd+Shift+R(Mac)强制刷新页面
  • 打开浏览器开发者工具(F12),切换到Network标签,勾选「Disable cache」,然后重新请求/api/users

Heroku的静态资产缓存

Heroku默认会对build目录下的静态文件设置较长的缓存时间,但API请求理论上不会被缓存。不过可以给API路由手动设置不缓存的响应头,避免意外:

// 在API路由里添加缓存控制头
app.get('/api/users', (req, res, next) => {
  res.set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
  next();
}, UserController.get);

另外,也可以在Heroku上清除应用缓存:进入应用的「Settings」标签,拉到最底部找到「Purge Cache」按钮点击即可;如果没有这个按钮,重新部署一次也能清除旧的缓存。

4. 确认React应用的构建是否正确

如果你的React应用没有正确构建,Heroku可能会用旧的build文件,甚至 fallback到默认的index.html。检查这些点:

  • 如果是本地构建后推送,确保front/build目录已经生成,并且里面的index.html是最新的
  • 如果让Heroku自动构建,要确保根目录的package.json里有正确的build脚本:
    "scripts": {
      "start": "node app.js",
      "build": "cd front && npm install && npm run build"
    }
    
    同时确认Heroku的buildpack是nodejs:可以用命令heroku buildpacks查看,要是不对就用heroku buildpacks:set heroku/nodejs设置。

5. 检查中间件的顺序

有没有其他中间件(比如cors、body-parser、日志中间件等)放在了API路由之后?比如如果app.use(cors())放在了静态文件路由之后,那API请求可能还没处理就被转到了静态文件。所有通用中间件都要放在API路由之前,除了静态文件和通配符路由。

如果以上都没用,就去看Heroku的实时日志:在终端运行heroku logs --tail,然后请求/api/users,看看日志里显示这个请求被哪个路由处理了——是匹配到了/api/users还是被*通配符接管了,这样能快速定位问题所在。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:27:27