react-router hash mode 转为 history mode 踩坑记结果你猜怎么着,点击到某个路由,手动
今天老板让我把 hash mode
改为 history mode
我想这还不简单吗
import {HashRouter as Router} from 'react-router-dom';
<Router hashType="noslash">
<App />
</Router>
// ----- 转化为----
import {BrowserRouter as Router} from 'react-router-dom';
<Router>
<App />
</Router>
结果你猜怎么着,点击到某个路由,手动刷新后白屏了。
- Q:为啥会白屏呢?
- A:是因为
html
里引用的js
找不到了 - Q:为啥
hash router
找得到对应的js
文件,history router
就找不到呢?
在 hash
模式下,当前路由为http://localhost::8080/#/square/publish
其查找的是根路径下的文件,所以能正确命中对应的资源。
而在 history
模式下,当前路由为http://localhost::8080/square/publish
经测试,http://localhost::8080/square/publish
路径下放的资源,它会在http://localhost::8080/square/
这个路径下查找。也就是说,在这个设置下,资源路径为相对于当前目录的地址,我们需要将其变为相对于根路径的地址。
那么这个经过 webpack
编译后html
文件中 script
的 src
是哪里来的呢,让我们看看 webpack
源码
// eslint-disable-next-line no-unused-vars
function hotDownloadUpdateChunk(chunkId) {
var script = document.createElement("script");
script.charset = "utf-8";
script.src = $require$.p + $hotChunkFilename$;
if ($crossOriginLoading$) script.crossOrigin = $crossOriginLoading$;
document.head.appendChild(script);
}
...
const publicPath = this.getPublicPath({
hash: hash
});
buf.push("");
buf.push("// __webpack_public_path__");
buf.push(`${this.requireFn}.p = ${JSON.stringify(publicPath)};`); // 这里就是上面的 $require$.p
return Template.asString(buf);
});
this.requireFn = "__webpack_require__";
由源码可知,script.src
是经由 $require$.p + $hotChunkFilename$
拼接而来的,查找 $require$.p
赋值的位置可得,其来源于 publicPath
,由此可得我们修改 webpack
配置
output: {
publicPath: '/',
},
就可将 <script src="[name].[hash:8].bundle.js" />
转化为 <script src="/[name].[hash:8].bundle.js" />
,那么它查找的路径便是相对于根路径,就能正确找到对应的 js
资源了。
==================== 更新 2020.1.19
===================
嗯,这件事还有后续,
由于发现项目中的多入口配置跟 history mode
冲突了,也就是说当寻找 0.0.0.0:8080/entry.html/main?id=${md5}
的时候,刷新了仍然是 GET 404
SO AWAFUL !!!
于是只好在 html
中设置
<base href="/">
这个设置跟上面 webpack
的作用是一致的,设置静态资源的路径为根路由。
然后,在 webpack
设置
devServer: {
historyApiFallback: {
verbose: true,
rewrites: [
{from: /^\/entry\/.*$/, to: '/entry.html'},
],
},
}
介个设置的意思是,在 url
为 localhost:8080/entry/main
, 它会重定向到 localhost:8080/entry.html/main
然后
当部署到服务器的时候,同样需要修改 nginx
配置,
location / {
rewrite ^/entry/(.+?) /entry.html/$1 last
}
===================== 我是卖萌的分界线 =====================
转载自:https://juejin.cn/post/6917551174375702535