React Router生产环境直接访问非根路由返回404问题求解
问题根因
这是BrowserRouter模式下单页应用(SPA)的典型路由问题:
- 开发环境webpack devServer开启了
historyApiFallback: true,所有不存在的路径请求都会自动返回根目录的index.html,由前端react-router接管路由匹配,所以直接访问子路由正常 - 生产环境用
serve启动时默认没有开启SPA回退逻辑,直接访问/register这类路径时,serve会尝试查找dist目录下的register静态文件,找不到就返回404 - 点击Link跳转正常是因为跳转行为由前端JS控制修改浏览器地址栏,没有触发真实的服务器请求,不需要后端配合
解决方案
方案1:修改serve启动命令(最快适配当前部署方式)
给serve加上--single(缩写-s)参数,开启单页应用回退模式:
serve dist -s --no-clipboard --listen ${PORT:-3000}
加了这个参数后,所有不存在的静态资源请求都会自动返回index.html,前端路由就能正常匹配。
方案2:补全生产环境webpack配置(避免静态资源加载错误)
你当前webpack.prod.js没有配置output.publicPath,和开发环境保持一致加上该配置,避免子路由下加载静态资源路径错误:
const { merge } = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode: 'production', output: { publicPath: '/', } });
其他部署场景适配方案
如果后续不用serve部署,换成其他服务器也需要配置对应的回退规则:
- Nginx部署:在nginx配置文件的server块中添加如下配置
location / { try_files $uri $uri/ /index.html; } - Apache部署:在项目根目录添加.htaccess文件
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </IfModule> - 若不想配置服务器规则,可以把react-router的BrowserRouter换成HashRouter,路径会自带
#,不需要服务器做回退适配,但URL美观度会下降。
内容的提问来源于stack exchange,提问作者red house 87
相关产品推荐
相关产品推荐

