使用Sphinx与sphinx-reredirects处理URL重定向时如何保留URL片段?
我完全懂这种头疼的状况——网上到处都是带锚点的文档链接,要是丢了#example1这种片段,用户点进来直接看不到关键位置,体验差到爆炸。你之前用JavaScript抓重定向的思路没错,但问题出在:sphinx-reredirects默认生成的重定向(比如meta标签刷新)会在你的JS代码执行前就把页面跳走了,自然抓不到原URL的hash。
给你几个靠谱的解决办法,按优先级来:
1. 自定义sphinx-reredirects的重定向模板(最推荐)
sphinx-reredirects允许你指定自己的HTML模板来生成重定向页面,我们可以用这个模板写一段JS,自动把原URL的hash拼到目标地址上,完美保留片段。
步骤如下:
- 首先,在你的Sphinx项目根目录创建一个
redirect_template.html文件,内容如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>正在跳转...</title> </head> <body> <script> // 从模板变量获取预设的目标重定向地址 const targetUrl = "{{ redirect_url }}"; // 把当前页面的hash拼到目标地址后面 const finalRedirectUrl = targetUrl + window.location.hash; // 执行跳转 window.location.href = finalRedirectUrl; </script> </body> </html>
- 然后打开你的Sphinx配置文件
conf.py,添加一行配置,告诉sphinx-reredirects用我们的自定义模板:
REDIRECTS_TEMPLATE = "redirect_template.html"
- 最后重新构建你的文档,生成的重定向页面就会自动把原URL的hash带到新地址上了。
这个方法的核心是:用客户端JS来处理重定向,而不是依赖meta标签或者服务器端HTTP重定向——只有浏览器能拿到URL的hash片段,服务器是看不到的,所以必须在客户端处理。
2. 服务器端重定向的补充说明(如果你用了HTTP 301/302)
如果你的重定向是通过服务器配置(比如Nginx、Apache)实现的,而不是sphinx-reredirects生成的HTML页面,那服务器端是无法获取到URL的hash部分的(因为hash不会发送到服务器)。这种情况下,你还是得用客户端JS来处理,比如在旧URL对应的静态HTML文件里加入上面的JS重定向代码,和方法1的思路一致。
为什么你之前的JavaScript代码没生效?
你之前写的beforeunload事件监听,应该是加到了新页面里,但重定向是从旧页面(sphinx-reredirects生成的空页面)跳转到新页面,旧页面根本没机会加载你的JS代码就被默认的meta刷新跳走了。所以必须把JS代码放到旧的重定向页面里,而自定义模板就是最直接的方式。
备注:内容来源于stack exchange,提问作者David Ekete

