react-router-dom路由HashRouter模式迁移BrowserRouter踩坑

1,249 阅读1分钟

根据以往的阅读过一遍react-router-dom文档的经验,so easy嘛,不就把HashRouter换成BrowserRouter就OK了吗,我还是太年轻。纸上得来终觉浅,绝知此事要躬行,于是就开启了我的排坑之路!

我觉得Hash模式就挺好啊,大佬说影响SEO,担待不起,改,一顿操作猛如虎!

头一次加载OK,刷新页面丢失 此处可以判定是入口的main.xxxxxx.js加载不到,路径出了问题

hash模式下:http://localhost:8085/js/main.1f305855.js (找的是根路径)

history模式下: http://localhost:8085/home/js/main.1f305855.js (找的是相对路径)

那么这个经过 webpack 编译后html 文件中 script 的 src 是哪里来的呢,让我们看看 webpack 源码

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 资源了。

加了这个好像还是不行,翻webpack文档

devServer: {
  ...
  historyApiFallback: true
}

加上这一段,刷新再也不白屏了,稳如一匹野马!!!

一切准备就绪,发测试环境,又是一出车祸现场!人生在于折腾,继续搞

网上百度一下,原来是NGINX配置的问题,NGINX小白的同学可以学起来,你可以学得动的!!!

location / {
    root   html;
    index  index.html index.htm;
    add_header  Cache-Control  no-cache;
    try_files $uri $uri/ /index.html;
}

这下真的是稳如一批野马!

总结

1、HashRouter 改为 BrowserRouter

2、output 设置 publicPath

3、historyApiFallback: true

4、add_header Cache-Control no-cache; try_files $uri $uri/ /index.html;