React路由404问题:跳转正常但直接访问URL返回404
嘿,这个问题我太熟了!这是React单页应用(SPA)部署后非常常见的路由坑,我帮你拆解下原因和解决办法:
问题根源
当你在页面内通过React Router从路由A跳转到路由B时,整个过程是前端JS在处理路由切换,没有向服务器发送新的请求;但直接复制路由B的URL访问时,浏览器会向服务器发起一个真实的HTTP请求,而服务器上根本不存在/offers/Arya-Ceremonial-Pool-VIP-off这个路径的物理文件,所以服务器就返回了404错误。
解决方案(优先推荐服务器配置)
核心思路是让服务器把所有路由请求都转发到你的SPA入口文件(一般是index.html),交给React Router来处理路由逻辑。
如果你用Nginx
修改你的Nginx站点配置文件(比如/etc/nginx/sites-available/your-site.conf),在location /区块中添加重写规则:
location / { # 先尝试访问文件或目录,找不到就转发到index.html try_files $uri $uri/ /index.html; }
保存配置后,重启Nginx生效:
sudo systemctl restart nginx
如果你用Apache
在项目根目录创建或修改.htaccess文件,添加以下规则:
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / # 直接访问index.html时不做处理 RewriteRule ^index\.html$ - [L] # 如果请求的不是文件或目录,就转发到index.html RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </IfModule>
注意要确保Apache已经开启了mod_rewrite模块。
如果你用Node.js Express服务器
在你的Express服务代码中,添加路由 fallback 逻辑:
const path = require('path'); // 先托管build目录下的静态文件 app.use(express.static(path.join(__dirname, 'build'))); // 所有未匹配到的请求都返回index.html app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'build', 'index.html')); });
临时替代方案:改用HashRouter
如果暂时没法修改服务器配置,可以快速切换到HashRouter。这种路由模式会在URL中加入#(比如http://test.shadyab.com/#/offers/Arya-Ceremonial-Pool-VIP-off),浏览器不会把#后面的内容发送给服务器,自然就不会出现404。
修改你的路由代码:
// 替换原来的Router导入 import { HashRouter, Route, IndexRoute } from 'react-router' // 把Router组件替换成HashRouter <Provider store={store}> <HashRouter> {/* 你的路由配置内容 */} </HashRouter> </Provider>
不过这个方案会让URL不够美观,还可能对SEO有一定影响,所以只建议作为临时过渡方案。
内容的提问来源于stack exchange,提问作者S.M_Emamian

