最近更新了开源组件的文档,完全重写了一遍。其中大部分内容都是通过配置完成的,页面都是基本的渲染模板,通过 v-html
来渲染出来的具体内容。此时,就会出现:当需要展示一个跳转链接时,却发现使用不了 <RouterLink>
跳转组件,只能使用 <a>
标签的时候。但是 <a>
标签跳转的连接,却无法实现多非根目录下的内容的跳转,毕竟 url 的路径都是通过 SPA 提供的路由模式解决的。
跳转的方式
一般来说,我们遇到路径跳转问题,都有几种办法:
- 将路由模式改为 HASH 模式,这样会显式的看到真正的路径
- 如果部署在服务器上,可以通过修改 Nginx、Apache 等反向代理,来重定向到指定页面
- 项目本身写一个 404 页面,然后跳转
由于文档部署在 Github Pages,并且它的很多页面都需要业内跳转,也就是它本身每个页面还需要hash定位跳转,所以前两种方式在这里并不合适,我们直接写一个 404 页面来实现跳转,只不过在写针对 Github Pages 的页面时,它给我们提供了一个非常好用的参数。
通过 404 页面跳转
1、Vite 配置打包
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
base: '/gantt/', // 根路径
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
build: {
outDir: 'dist',
assetsDir: 'assets',
// 确保 404.html 被正确复制到根目录
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
404: resolve(__dirname, 'public/404.html') // 需要打到指定位置,替换原 404 页面
}
}
}
})
2、创建自己的 404 页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>页面重定向中...</title>
<meta name="robots" content="noindex">
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f5f5f5;
}
.container {
text-align: center;
background: white;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
<script type="text/javascript">
// GitHub Pages SPA 路由重定向解决方案
(function() {
var pathSegmentsToKeep = 1; // Github Pages 关键参数
var l = window.location;
// 构建重定向URL
var redirect = l.protocol + '//' + l.hostname +
(l.port ? ':' + l.port : '') +
l.pathname.split('/').slice(0, 1 + pathSegmentsToKeep).join('/') +
'/?/' +
l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
(l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
l.hash;
console.log('Redirecting from:', l.href, 'to:', redirect);
// 使用 replace 避免在浏览器历史中留下记录
setTimeout(function() {
l.replace(redirect);
}, 0);
})();
</script>
</head>
<body>
<div class="container">
<h2>页面加载中...</h2>
<div class="spinner"></div>
<p>正在为您跳转到正确的页面,请稍候...</p>
<!-- 这里需要写自己的首页路径,与 vite 中配置的 根路径 保持一致 -->
<p>如果页面没有自动跳转,请 <a href="/gantt/">点击这里</a> 返回首页</p>
</div>
</body>
</html>
Github Pages 的特殊参数
pathSegmentsToKeep
决定了在重定向 URL 中需要保留多少个路径段,这直接影响到重定向的正确性。
具体示例
假设你的 GitHub Pages 站点 URL 结构如下:
-
情况1:仓库名部署 (pathSegmentsToKeep \= 1)
原始 URL: https://username.github.io/gantt/docs/api 分解: * Protocol: https:// * Hostname: username.github.io * Path segments: ['', 'gantt', 'docs', 'api'] * 保留段数: 1 (即保留 'gantt')
重定向后的 URL:
https://username.github.io/gantt/?/docs/api
-
情况2:用户主页部署 (pathSegmentsToKeep \= 0)
原始 URL: https://username.github.io/docs/api 分解: * Protocol: https:// * Hostname: username.github.io * Path segments: ['', 'docs', 'api'] * 保留段数: 0 (不保留任何段)
重定向后的 URL:
https://username.github.io/?/docs/api
3、在 index.html 中添加路由恢复脚本
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- GitHub Pages 路由恢复脚本 -->
<script type="text/javascript">
// 检查是否是从 404 页面重定向过来的
(function(l) {
if (l.search[1] === '/') {
var decoded = l.search.slice(1).split('&').map(function(s) {
return s.replace(/~and~/g, '&')
}).join('?');
var newUrl = l.pathname.slice(0, -1) + decoded + l.hash;
console.log('Restoring route from:', l.href, 'to:', newUrl);
window.history.replaceState(null, null, newUrl);
}
}(window.location));
</script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
发布
最后就是发布到 Github Pages,如果使用了工作流,那么不要忘记打包时将 404.html 页面一并发布到项目中即可。
name: 部署文档
on:
push:
branches: [master]
paths:
- 'docs/**'
jobs:
create-gh-pages:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- name: 检查分支
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: xxx
run: xxx
- name: 创建发布目录并确保 404.html 在根目录
run: |
mkdir -p gh-pages/
cp -r docs/dist/* gh-pages/
# 确保 404.html 在根目录
if [ -f "docs/public/404.html" ]; then
cp docs/public/404.html gh-pages/404.html
fi
# 验证文件结构
echo "Generated files:"
ls -la gh-pages/
if [ -f "gh-pages/404.html" ]; then
echo "✅ 404.html found in root"
else
echo "❌ 404.html NOT found in root"
fi
文章评论