解决问题:Github(Gitee) Pages上的Vue项目刷新页面时子路由报404

746 阅读2分钟

本文摘自我的个人博客 ,未经允许请勿转载。

遇到问题

之前试着把手搓的个人博客部署到Github Pages上。部署过程不难,网页也如预期加载。然后我随手刷新了一下,发现除了首页以外,子路由都会报404。

我想大概是Vue Router的原因,事实也的确是这样。

浏览器刷新时,如果路径改变,就会按照路径发送资源请求。但此时的URL是Vue Router在History模式下设置的,直接按此请求肯定找不到资源,于是就返回404了。

解决问题

1. 寻找方案

我在网上查了下,找到了三种主流解决办法:

  • 后端添加重定向
  • 改用Hash路由
  • 在index.html所在目录下直接添加一个内容与之相同的404.html

第一种方法想都不用想,Github(Gitee) Pages仅支持托管静态页面

第二种方法会给URL增加井号,不咋美观。而且我的文章toc定位就是用便捷的锚点链接实现的,我不想为了改用Hash路由就重写个定位方式甚至直接放弃toc定位,所以也没采用。

第三种方法思路对了一半。该方法利用了Github(Gitee) Pages支持自定义404页面的功能,在404.html中渲染与原网页相同的内容以防止网页丢失。但该方法仅在普通页面里可行,在Vue项目里不适用。毕竟,不可能又在404.html里面挂载根组件吧?这也太蠢了。我们换个思路,其实只需要把404.html当作跳板,重定向回相应路由即可。

2. 实施过程

  1. 在public目录下新建404.html,并在head标签中添加了:
  <script>
    sessionStorage.redirect = location.href;
  </script>
  <meta http-equiv="refresh" content="0; URL='/'">
  1. 在index.html中body标签上方添加了:
<script>
  (function () {
    const redir = sessionStorage.redirect;
    delete sessionStorage.redirect;
    if (redir && redir !== location.href) {
      history.replaceState(null, null, redir);
    }
  })();
</script>

这样,跳转至404.html时会保存此时的地址,然后立即刷新并导航至根链接(即回到index.html),index.html在加载body前用保存的地址替换掉根链接,这样Vue Router就能据此正确地导航回来了。

涉及知识点

前端路由

前端路由有两种模式,Hash和History。

Hash:利用锚点定位原理,哈希值改变时触发hashChange事件并执行改变DOM的回调函数。这是前端Hash路由的基本原理。

  • 优点:
    • 兼容性佳
    • 无需后端参与,
  • 缺点:
    • URL不美观
    • 占用了锚点定位功能

History:利用H5中History API新增的pushState、replaceState方法,直接更改URL而不用重新请求。

  • 优点:
    • URL美观,符合规范
  • 缺点:
    • 兼容性不如Hash
    • 基于此的SPA页面需要后端设置重定向