一、问题/场景描述
在使用 React 单页应用(SPA)开发时,经常遇到这样的问题:当用户通过 React Router 的 Link 或 history.push 进行页面内跳转时,一切正常;但一旦手动刷新浏览器(F5 或刷新按钮),页面就会显示空白或 404 错误,控制台提示资源加载失败,导致应用无法正常使用。这一问题在部署到生产环境后尤为常见,严重影响用户体验。
二、原因分析
根本原因在于 React Router 默认使用 HTML5 History API(如 BrowserRouter)来管理路由,其路径是真实 URL(如 /about)。当用户直接访问或刷新该路径时,浏览器会向服务器发起对该路径的 HTTP 请求。由于服务器没有配置相应的处理规则,它通常会尝试查找 /about 文件或将其视为 API 端点,导致返回 404 或空白页面。常见的场景包括:开发环境使用 webpack-dev-server 未配置 historyApiFallback,生产环境使用 Nginx、Apache 或 Node.js 服务器未正确配置 fallback 到 index.html。此外,React 应用打包后的静态资源(如 JS、CSS)路径错误也可能导致刷新后资源加载失败,但主要问题在于服务器端路由与客户端路由不匹配。
三、详细解决步骤
步骤 1:确认路由模式
首先检查你的 React 应用是否使用了 BrowserRouter。如果是 HashRouter(URL 中包含 #),刷新通常不会出现此问题,但 URL 不美观。若确认是 BrowserRouter,请继续以下步骤。
步骤 2:开发环境配置(webpack-dev-server)
如果你使用 Create React App 或自定义 webpack 配置,开发环境下刷新空白是因为 webpack-dev-server 未处理 fallback。在 webpack.config.js 的 devServer 中添加:
devServer: {
historyApiFallback: true,
}
对于 Create React App,该配置默认已开启,无需额外设置。
步骤 3:生产环境配置 – Nginx
假设你的应用部署在 Nginx 服务器上,需要修改 Nginx 配置文件(通常位于 /etc/nginx/nginx.conf 或站点配置文件中),找到 server 块,添加以下 try_files 指令:
location / {
try_files $uri $uri/ /index.html;
}
这告诉 Nginx:如果请求的路径不是静态文件,则返回 index.html,由 React Router 处理客户端路由。修改后执行 sudo nginx -s reload 使配置生效。
步骤 4:生产环境配置 – Apache
如果使用 Apache,需要在 .htaccess 文件(位于项目根目录)中添加:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html [L]
确保 Apache 启用了 mod_rewrite 模块。
步骤 5:生产环境配置 – Node.js(Express)
如果你使用 Express 作为后端服务器,在路由处理前添加:
app.use(express.static(path.join(__dirname, 'build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
步骤 6:验证静态资源路径
如果刷新后页面不白但资源加载失败(如 JS 404),检查 package.json 中的 homepage 字段或 webpack 的 publicPath 是否正确。例如,若部署在子路径 /app 下,需设置:
"homepage": "/app"
或 webpack 配置:
output: {
publicPath: '/app/',
}
四、注意事项
1. 修改服务器配置后,务必重启或重载服务(如 Nginx reload)。2. 使用 HashRouter 可以完全避免此问题,但 URL 会带 #,不利于 SEO。3. 如果应用部署在 CDN 或静态托管平台(如 Netlify),通常有对应的 fallback 设置(如 Netlify 的 _redirects 文件)。4. 确保所有静态资源(JS、CSS、图片)的路径正确,避免因路径错误导致资源加载失败。
五、适用环境
本文适用于 React 16+ / 17+ / 18+ 版本,配合 BrowserRouter 及 Nginx 1.18+ / Apache 2.4+ / Node.js 14+ 环境。
