部署在Heroku的Node.js Express应用无法接收React客户端请求
修复Express生产环境下API路由无法触发的问题
问题核心出在路由注册顺序:你把生产环境的通配GET *路由放在了/cityAPI路由前面,导致所有GET请求(包括/city)都被优先匹配到返回React的index.html,根本不会进入/city的处理逻辑。
解决步骤
- 调整路由顺序:Express会按照路由注册的先后顺序匹配请求,先匹配到的路由会处理请求,后续路由不再执行。所以要把所有API路由(比如
/city)放在生产环境的静态文件服务和通配路由之前。 - (可选)补全客户端请求URL:你的请求URL
myherokusite.com/city?name=xxx缺少协议头https://,虽然浏览器可能自动补全,但显式加上能避免潜在路径解析问题。
修改后的服务端index.js关键部分
const express = require('express') const app = express(); const port = 3000; const cors =require('cors'); const request = require('request'); const words = require('./words'); require('dotenv').config(); const path = require('path'); const apiKey=process.env.apiKey; // 先注册API路由 app.get('/city',(req,res)=>{ console.log("allo allo"); const cityname = req.query.name; let resArray=[]; request({ uri:'https://maps.googleapis.com/maps/api/place/textsearch/json', qs:{ query:"point of interest in"+cityname, key:apiKey } },(err,request,body)=>{ const object = JSON.parse(body); let photo; let placeObject={ placeName:'', photo:'' } for(let i=0;i<object.results.length;i++){ if(object.results[i].photos!==undefined){ placeObject['placeName']=words.returnWordsInEnglish(object.results[i].name); placeObject['photo'] =object.results[i].photos[0]['photo_reference']; } resArray[i]=Object.assign({},placeObject); } res.send(resArray); }); }); // 再注册生产环境的静态文件和通配路由 if (process.env.NODE_ENV === "production") { app.use(express.static(path.join(__dirname, '../client/dist'))); app.get("*", (req, res) => { res.sendFile(path.resolve(__dirname, "../client/dist", "index.html")); }); } app.listen(process.env.PORT||port, () => { console.log(`Example app listening on port ${process.env.PORT||port}!`) }); // ... 其他函数保持不变
客户端fetch请求优化(可选)
fetch(`https://myherokusite.com/city?name=${encodeURIComponent(searchValue)}`,{ method:'GET', credentials:'include', headers:{ 'Accept':'application/json', 'Content-Type':'application/json' } }).then((data)=>{ console.log("data"); console.log(data); return data.json(); }).then(data=>{ console.log(data); setResult(Object.entries(data)); }).catch(err => console.error('请求出错:', err)); // 添加错误捕获,方便排查问题
调整后,请求/city时会先匹配到API路由执行逻辑,其他未匹配的GET请求才会返回React的index.html,就能解决你遇到的问题。
内容的提问来源于stack exchange,提问作者Johhnny
相关产品推荐
相关产品推荐

