Express路由本地正常但生产环境失效(React+Apache反向代理)
我帮你分析下这个问题,这是React客户端路由在生产环境部署时非常常见的坑,咱们一步步来解决:
问题根源
你用的是React的BrowserRouter,这种路由是客户端路由——也就是说,页面跳转都是在浏览器端完成的,不会向服务器发请求。但当你刷新页面,或者直接在URL里输入/foo这类路由时,请求会先发送到Apache,Apache再转发给你的Express服务器。而你的Express服务器现在只处理了API路由、静态资源,以及手动指定的/login和/signUp/:id,其他路由都没有对应的处理,所以就返回了Cannot GET /foo的404错误。
本地开发时React Dev Server会自动兜底,把所有未匹配的请求都重定向到index.html,但生产环境需要我们手动给Express配置这个兜底逻辑。
具体解决方案
1. 给Express添加Catch-All兜底路由
打开你的server.js,在所有路由的最后(包括API路由、静态资源托管配置之后),添加这段代码:
// 所有API路由、静态资源配置之后添加这个兜底路由 app.get('*', (req, res) => { res.sendFile(__dirname + '/client/index.html'); });
这里的*表示匹配所有HTTP GET请求,只要前面的API路由、静态资源都没匹配上,就返回React的index.html,让React的客户端路由来处理路径。
另外,你现在手动写的/login和/signUp/:id路由其实可以删掉了——兜底路由会统一处理这些请求,这样代码更简洁,也不会遗漏其他路由。
2. 确认Apache配置(可选优化)
你的Apache反向代理配置基本没问题,不过可以补充一个Cookie相关的配置(如果后续遇到Cookie跨域问题的话),另外确保ProxyPreserveHost On是开启的,这样Express能拿到正确的请求主机信息:
<VirtualHost *:80> # ServerName domain.com # ServerAlias www.domain.com DocumentRoot "/www/html/360-nodejs" ProxyRequests Off ProxyPreserveHost On ProxyVia Full AllowEncodedSlashes On ErrorLog "/var/log/apache2error.log" CustomLog "/var/log/apache2errorcustom.log" common <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/ # 如果有Cookie相关问题,取消下面注释并替换成你的域名 # ProxyPassReverseCookieDomain 127.0.0.1 your-domain.com </VirtualHost>
验证流程
修改完之后按下面步骤测试:
- 重启你的Node.js服务器,让新的路由配置生效
- 重启Apache服务(执行
sudo service apache2 restart) - 尝试直接在URL输入
your-ip/intro、your-ip/signUp/任意字符,或者刷新已打开的路由页面,确认不再出现404错误,能正常加载对应组件
内容的提问来源于stack exchange,提问作者Loyd Fassi

