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

Create-React-App部署Heroku异常:访问根路径出现Cannot GET /错误

解决Heroku部署Node+React应用后显示"Cannot GET /"的问题

你的问题核心很明确:后端Express服务器没有配置静态文件服务来托管React的构建产物,也没有处理SPA的路由 fallback。本地开发时React的dev server帮你搞定了前端路由和API代理,但Heroku上是直接运行你的server.js,所以得让Express来负责提供前端页面。

问题根源分析

你的server.js只定义了/api/form这一个POST接口,完全没有处理根路径(/)或其他前端路由的GET请求逻辑。当用户访问Heroku应用的根路径时,Express找不到对应的路由匹配规则,自然就返回404错误了。

具体解决方案

修改你的server.js,添加静态文件托管和SPA路由兜底的代码,步骤如下:

  1. 引入Node.js内置的path模块(无需额外安装),用来处理文件路径;
  2. 配置Express托管React构建后的client/build目录,让它能返回前端静态资源;
  3. 添加一个catch-all路由,所有未匹配到API的GET请求都返回React的index.html,保证单页应用的路由能正常工作。

修改后的完整server.js代码如下:

const express = require('express');
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer');
// 引入path模块处理文件路径
const path = require('path');

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

// 托管React构建后的静态文件
app.use(express.static(path.join(__dirname, 'client/build')));

// 邮件API路由
app.post('/api/form', (req, res) => {
  nodemailer.createTestAccount((err, account) => {
    const htmlEmail = `
    <h3>Contact Details</h3>
    <ul>
      <li>Name: ${req.body.name}</li>
      <li>Email: ${req.body.email}</li>
    </ul>
    <h3>Message</h3>
    <p>${req.body.message}</p>
    `;

    let transporter = nodemailer.createTransport({
      host: 'smtp.ethereal.email',
      port: 587,
      auth: {
        user: 'config',
        pass: 'config'
      }
    });

    let mailOptions = {
      from: 'config',
      to: 'config',
      replyTo: 'config',
      subject: 'New message',
      text: req.body.message,
      html: htmlEmail
    };

    transporter.sendMail(mailOptions, (err, info) => {
      if(err){
        console.log(err);
        return res.status(500).json({ success: false, message: '邮件发送失败' });
      }
      console.log('Message sent: %s', info.message);
      console.log('Message URL: %s', nodemailer.getTestMessageUrl(info));
      // 给前端返回响应,避免请求挂起
      res.status(200).json({ success: true, message: '邮件发送成功' });
    });
  });
});

// Catch-all路由:所有未匹配API的GET请求返回React的index.html
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, '/client/build/index.html'));
});

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log('Server listening on port ' + PORT);
});

额外注意点

  • 你的heroku-postbuild脚本是正确的,它会在Heroku上安装client依赖并生成build目录,确保构建产物存在;
  • 本地开发时的proxy配置只在React dev server生效,Heroku部署后不需要这个配置,因为后端直接托管了静态文件;
  • 我在邮件API里补充了响应返回逻辑,避免前端axios请求一直处于pending状态。

验证方式

修改后重新推送到Heroku,等待部署完成后访问应用,应该就能正常加载React页面了。如果还有问题,可以通过heroku run bash进入Heroku容器,检查client/build目录是否存在以及文件是否完整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:53:59