React Router v6与AWS S3重定向规则适配问题求解
解决AWS S3 + React Router v6移除#!路由前缀的方案
方案一:S3重定向参数 + React客户端处理
- 调整S3重定向规则
替换原有的#!重定向配置,将不存在的请求重定向到/index.html并携带原始路径作为查询参数。在S3静态网站托管的重定向规则中添加以下配置:
[ { "Condition": { "HttpErrorCodeReturnedEquals": "404" }, "Redirect": { "HostName": "你的S3网站域名", "HttpRedirectCode": "302", "Protocol": "https", "ReplaceKeyWith": "index.html?redirect=$requestURI" } } ]
此配置会将/about这类404请求重定向到/index.html?redirect=/about,避免自动添加#!前缀。
- React客户端处理参数导航
在<BrowserRouter>包裹的组件内部(保证处于Router上下文),通过useNavigate和useLocation处理查询参数,导航到真实路径:
import { useEffect } from 'react'; import { useNavigate, useLocation, Routes, Route } from 'react-router-dom'; import Home from './pages/Home'; import About from './pages/About'; function App() { const navigate = useNavigate(); const location = useLocation(); useEffect(() => { const searchParams = new URLSearchParams(location.search); const redirectPath = searchParams.get('redirect'); if (redirectPath) { const cleanPath = redirectPath.startsWith('/') ? redirectPath : `/${redirectPath}`; // 用replace模式避免历史记录冗余 navigate(cleanPath, { replace: true }); } }, [navigate, location.search]); return ( <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> {/* 其他路由配置 */} </Routes> ); } export default App;
确保根组件使用BrowserRouter而非HashRouter:
import { BrowserRouter as Router } from 'react-router-dom'; import App from './App'; ReactDOM.createRoot(document.getElementById('root')).render( <Router> <App /> </Router> );
- 设置index.html缓存策略
在S3中给index.html设置缓存控制为no-cache,避免浏览器缓存旧页面导致参数处理失效。
方案二:CloudFront + Lambda@Edge(更优SEO方案)
如果对SEO要求较高,推荐用CloudFront配合Lambda@Edge在服务器端处理路径重写,无需客户端跳转:
- 编写Lambda@Edge函数
创建Node.js函数,识别静态资源请求,将非静态资源请求重写到index.html:
exports.handler = async (event) => { const request = event.Records[0].cf.request; const uri = request.uri; // 匹配静态资源后缀,直接放行 const staticAssetRegex = /\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf)$/; if (staticAssetRegex.test(uri)) { return request; } // 非静态资源请求重写到index.html,保留原始路径供React Router处理 request.uri = '/index.html'; return request; };
注意:Lambda函数需部署在us-east-1区域,才能关联到CloudFront。
关联Lambda到CloudFront
在CloudFront控制台中,将上述Lambda函数关联到Viewer Request事件,所有请求到达S3前会先经过Lambda处理。更新S3配置
无需设置S3静态网站托管的错误文档,CloudFront已将非静态资源请求转发到index.html,React Router可以直接处理原始路径,完全避免#!前缀。
此方案无客户端跳转,URL保持干净,对SEO更友好,同时规避了S3错误文档设置带来的潜在SEO风险。
内容的提问来源于stack exchange,提问作者DDD
相关产品推荐
相关产品推荐

