抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

github pages 在遇到根目录之外的 url,会直接去根目录找对应文件,找不到就 404
这和期望部署的单页面 app 是不符的,我还是希望能用 vue router 的 history 模式,url 好看的单页面应用
所幸 github pages 在找不到会先默认进入 404.html,所以可以通过这个页面来重定向,解决这个问题

前言

用 vue 写了个静态页面,懒得弄服务器,所以直接部署在 github pages 上
用了 Vue Router,是个单页面应用,一般来说应该可以通过 url 直接进入 spa 的某页面
比如说 https://sb6657.cn/search?s=ququ 应该直接进搜索页搜索 ququ

但是部署完发现直接白屏啥都没有,查了查原来是 github pages 没有默认处理路由,没有把所有请求都定向到 index.html 导致的
它会在遇到非/路由的时候直接去根目录找对应文件,找不到就重定向到 404.html,这个也没有的话就直接白屏了

解决

hash 路由

两个方案,第一是用 hash 路由,github pages 不会处理 hash 路由,所以能用,vue router 里开启 hash 模式就行了
不过 url 里带个#确实不好看也不好用,所以我不想用

在 404.html 中重定向

方案二就是利用了找不到相应文件会进入 404.html 的特性,在这里记录输入 url,重定向回主页再操纵就行了。
要改的是,加一个 404.html,改一下 App.vue

我用的 vue3 + vite + typescript,顺带解决一下页面部署之后不在根 url 的页面定向问题
所以还再加改一个 vite.config.ts

404.html

/public里建一个 404.html,存当前 path 并重定向,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>YOUR TITLE</title>
<script>
/**
* 应对github page之类的部署单页面应用时,重定向错误问题
* 这种遇到url会直接去根目录找对应文件,如果没有就直接进入404.html
* 所以在404.html里暂存当前路径,然后重定向回首页,首页再改url就能实现单页面应用
*/
// 如果你的页面访问路径是 www.xxx.com/projectname ,这里就填'/projectname'
// 如果访问路径直接是 www.xxx.com根目录,就直接填'/'
// 注意vite.config.ts也要相应更改
const projectName = '/projectname';

let relativePath = location.pathname;
// 路径以项目名开头时,移除掉。不然会因为vite的处理,重复一次
if (relativePath.startsWith(projectName)) {
// 移除基础路径
relativePath = relativePath.substring(projectName.length);
}
// 添加查询字符串
if (window.location.search) {
relativePath += window.location.search;
}
// 保存最终的路径到sessionStorage,用于SPA中的重定向
sessionStorage.setItem('redirect', relativePath);
// 重定向到基础路径
window.location.href = projectName;
</script>
</head>
<body></body>
</html>
App.vue

改 App.vue,在页面加载之前,获取之前 404.html 里存的路径,在这再改回去

1
2
3
4
5
6
7
8
9
10
11
import { useRouter } from 'vue-router';
import { onBeforeMount } from 'vue';
// 应对github page之类的重定向,实现部署spa能用url查询定向
const redirect = sessionStorage.getItem('redirect');
onBeforeMount(async () => {
if (redirect) {
console.log('重定向到', redirect);
await useRouter().push(redirect);
sessionStorage.removeItem('redirect');
}
});
vite.config.ts

这里解决一下不是根目录的 url 部署页面的问题
如之前的注释,如果页面访问路径是 www.xxx.com/projectname ,这里就填'/projectname/'
如果访问路径直接是 www.xxx.com根目录,就直接填'/'

1
2
3
export default defineConfig({
base: '/projectname/',
});

注:不写 base 属性的话,默认值是'/'

总结

利用 404.html 里保存了当前的路径,本地暂存下,传给 Vue,再改 url 就不被 github pages 限制了

评论