使用.htaccess时带哈希标签的永久重定向失效问题
这个问题的核心原因很关键:浏览器不会把URL中#后面的锚点部分发送给Web服务器。也就是说,当用户访问www.example.com/parentpage-childpage#samplepage时,你的Apache服务器实际收到的请求路径只有/parentpage-childpage,完全看不到#samplepage这部分内容。
这就导致你写的RedirectPermanent /parentpage-childpage#samplepage /parentpage/child-page/sample-page规则根本不会被触发——Apache找不到任何匹配这个带锚点的路径的请求。如果之前有匹配/parentpage-childpage的重定向规则(或者WordPress默认的 permalink 规则),就会优先触发那条规则,把请求重定向到/parentpage/child-page,然后浏览器会自动把原URL里的锚点#samplepage追加到新URL后面,最终变成你看到的www.example.com/parentpage/child-page#sample-page。
下面给你两种可行的解决方案:
方案一:客户端JavaScript处理(最直接,无需修改原URL)
既然服务器拿不到锚点,我们可以在重定向后的目标页面里加一段JS,检查当前URL的锚点,如果是#samplepage,就自动跳转到最终的目标页面:
- 先在
.htaccess里保留基础的重定向规则(去掉锚点部分):
RedirectPermanent /parentpage-childpage /parentpage/child-page
- 编辑WordPress中
parentpage/child-page对应的页面模板(或者在页面的自定义HTML区块里添加),插入这段JavaScript:
window.addEventListener('DOMContentLoaded', function() { // 检查当前URL的锚点是否为#samplepage if (window.location.hash === '#samplepage') { // 跳转到最终目标页面,replaceState可以避免在浏览器历史中留下中间页面记录 window.location.replace('/parentpage/child-page/sample-page'); } });
这样用户访问原URL时,会先被重定向到/parentpage/child-page,然后JS检测到锚点后自动跳转到/parentpage/child-page/sample-page,完全符合你的期望。
方案二:修改原URL格式(服务器端处理,需控制原URL生成)
如果能修改生成原URL的地方(比如把旧页面的链接从#samplepage改成带查询参数的格式),可以用Apache的mod_rewrite来实现纯服务器端重定向:
- 把原URL改成
www.example.com/parentpage-childpage?anchor=samplepage(用查询参数代替锚点) - 在
.htaccess中添加以下规则(确保RewriteEngine On已经开启):
RewriteEngine On # 匹配带anchor=samplepage查询参数的请求 RewriteCond %{QUERY_STRING} ^anchor=samplepage$ # 重定向到目标页面,末尾的?是为了去掉原查询参数 RewriteRule ^parentpage-childpage$ /parentpage/child-page/sample-page? [R=301,L]
这种方式不需要依赖JS,但前提是你能控制旧链接的生成格式,把锚点换成查询参数。
内容的提问来源于stack exchange,提问作者Gold Pearl

