React多实例复用公共静态资源时react-router路由失效如何解决?
问题根因
路由无法匹配的核心原因有两点:
- react-router的
Route组件path属性仅支持匹配URL的路径部分,不支持传入带域名的完整绝对地址,你当前传入带域名前缀的process.env.REACT_APP_INSTANCE_URL自然无法匹配成功 BrowserRouter没有配置对应实例访问路径的basename属性,路由基准路径错误
修复方案
方案一:调整React路由配置(推荐)
此方案无需额外服务端配置,改造成本最低。
- 调整env变量定义,仅保留路径部分,不要带域名前缀,该变量可以直接写在每个实例独立的
index.html中,不需要打包进公共静态资源,不影响公共资源复用性:
REACT_APP_INSTANCE_PATH=/sites/instance1/react-app
- 修改路由配置,给
BrowserRouter增加basename属性,路由路径直接写相对路径即可:
<BrowserRouter basename={process.env.REACT_APP_INSTANCE_PATH}> <Switch> <Route path="/" exact render={() => <HomePage />} /> {/* 其余路由直接写相对路径即可自动适配基准路径 */} <Route path="/user" render={() => <UserPage />} /> ... </Switch> </BrowserRouter>
方案二:通过htaccess实现(无需改业务代码)
如果不想调整前端代码,可在站点根目录新增.htaccess文件实现需求:
<IfModule mod_rewrite.c> RewriteEngine On # 1. 所有实例的静态资源请求统一重定向到公共base-react-app目录 RewriteRule ^sites/([^/]+)/react-app/(.*\.(js|css|png|jpg|svg|ico|woff2?|json))$ /base-react-app/$2 [L] # 2. 适配BrowserRouter刷新404问题,非静态资源请求返回对应实例的index.html RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^sites/([^/]+)/react-app/(.*)$ /sites/$1/react-app/index.html [L] </IfModule>
额外优化建议
- 可以在每个实例的
index.html中单独配置<base href="/base-react-app/" />标签,替代package.json中写死的homepage配置,适配性更强 - 公共静态资源可配置强缓存,版本更新时通过构建生成的文件名hash实现缓存更新,提升加载性能
内容的提问来源于stack exchange,提问作者Mohammad
相关产品推荐
相关产品推荐

