React Router v5 生产环境嵌套路由失效问题排查
HashRouter转BrowserRouter后生产环境Nginx 404问题
问题描述
近期将项目中的HashRouter替换为BrowserRouter,开发环境通过在webpack.dev.config添加以下配置可正常运行:
devServer: { historyApiFallback: true, allowedHosts: 'all', },
但生产环境中:
- 访问
myapp.com可正常加载 - 访问
myapp.com/home或myapp.com/intro时返回Nginx 404错误 - 访问
myapp.com/#/home会自动重定向到myapp.com/home且页面可正常渲染(已配置兼容旧hash路径的全局转换逻辑)
现有Webpack配置
webpack.common.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: path.join(__dirname, 'src', 'index.js'), output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', chunkFilename: '[id].js', publicPath: '/', hashFunction: 'xxhash64', }, resolve: { extensions: ['.js', '.jsx'], }, module: { rules: [ { test: /\.(scss)$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'postcss-loader', options: { postcssOptions: { plugins: function () { return [require('autoprefixer')] }, }, }, }, { loader: 'sass-loader' }, ], }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'], }, }, }, { test: /\.css$/, exclude: /node_modules/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: { localIdentName: '[name]__[local]___[hash:base64:5]', }, sourceMap: true, }, }, { loader: 'postcss-loader', options: { postcssOptions: { plugins: [['autoprefixer', {}]], }, }, }, ], }, { test: /\.(png|jpe?g|gif|svg)$/, use: [ { loader: 'url-loader', options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' }, }, ], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: __dirname + '/public/index.html', filename: 'index.html', inject: 'body', favicon: './public/favicon.ico', manifest: './public/manifest.json', }), ], }
webpack.prod.js
const { merge } = require('webpack-merge'); const common = require('./webpack.common.js'); const Dotenv = require('dotenv-webpack'); module.exports = merge(common, { mode: 'production', performance: { hints: false, maxEntrypointSize: 512000, maxAssetSize: 512000, }, plugins: [ new Dotenv({ path: './.env', }), ], })
解决方案
问题出在Nginx未配置路由 fallback,开发环境的historyApiFallback: true会把所有路由请求转发到index.html,但生产环境需要在Nginx中做相同配置。
修改Nginx的站点配置文件(通常位于/etc/nginx/sites-available/或/etc/nginx/conf.d/目录下),添加try_files指令:
server { listen 80; server_name myapp.com; root /path/to/your/project/dist; # 替换为实际的dist目录绝对路径 location / { # 优先尝试访问请求的文件/目录,找不到则返回index.html try_files $uri $uri/ /index.html; } }
配置完成后,重启Nginx生效:
sudo systemctl restart nginx
说明
BrowserRouter依赖前端路由接管,当用户直接访问myapp.com/home时,Nginx会尝试寻找服务器上的home文件或目录,找不到就返回404。添加try_files后,所有找不到的资源请求都会转发到index.html,由React应用处理路由逻辑,就能正常渲染对应页面了。
内容的提问来源于stack exchange,提问作者Damian
相关产品推荐
相关产品推荐

