用重定向去掉博文的 .html 后缀

2022-10-15-11-15-02

谷月姐最近有一个需求,就是用重定向(准确地说是 301 跳转)去掉博文的 .html 后缀,例如,把形如 https://blog.kukmoon.com/834aa795.html 的 URL 转变成 https://blog.kukmoon.com/834aa795/ (注意最后的斜杠)的形式。

01 S 场景

虚拟主机快到期了,我不想再续费了,想把博客部署到一个免费的托管平台。

找来找去,找到了 Cloudflare Pages (下文简称 CF Pages)。CF Pages 不用花钱,可以与 GitHub 无缝对接,在墙内外都有节点,非常适合我部署 本博

02 C 冲突

CF Pages 会强行忽略 URL 中的 .html 后缀,例如,让形如 https://blog.kukmoon.com/834aa795.html 的网址 302 重定向到形如 https://blog.kukmoon.com/834aa795 (注意最后没有斜杠)的网址。官方称之为 Route Matching (路由匹配)[1]。经测试,它无法手动关闭。

这个问题产生了两个负面影响:

  1. 这个功能影响了评论的加载[2]本博 的评论系统是 Valine,它是根据静态页面的文件名来储存评论数据的,比方说,它会把 https://example.tld/file123.html 这个页面的所有评论放在数据库的 file123.html 表中。所以 本博 不同镜像的同一篇文章会共享同样的评论。但是 Route matching 去掉了 .html 后缀,导致 Valine 评论系统会在数据库新建一个 file123 表,从而使得部署在 CF Pages 上的 本博镜像 不能与其他的镜像共享评论。

  2. 这个功能影响了搜索引擎的收录与检索。搜索引擎收录的 URL 是含有 .html 后缀的,如果去掉了这个后缀,就势必会影响搜索引擎的收录与检索。

所以,我要是把博客从虚拟主机迁移到 CF Pages,就需要妥善地处理 Route Matching 带来的这两个负面影响。

03 Q 问题:301 跳转

我的解决方案是,在虚拟主机和 CF Pages 两边都配置 301 跳转,去掉 .html 后缀,让两边的 URL 保持一致。这样,一方面可以共享评论,另一方面也不影响搜索引擎的收录和检索。

现在问题来了,如何配置 301 跳转呢?

不同的服务端,配置 301 跳转的方法不同。

我的虚拟主机用的服务端是 Apache (CPanel 面板用的是 Apache)。CF Pages 也有自己的方法。本文只介绍这两种方法。

04 A 解决:配置 301 跳转的方法

4.1 在虚拟主机上配置 301 跳转

我的虚拟主机用的是 CPanel 面板,它是用 Apache 作为 Web 服务端,需要编写 .htaccess 文件配置 301 跳转。

新建一个名为 .htaccess 的文件(如何新建以点开头的文件,请自行谷歌搜索),填入内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php56” package as the default “PHP” programming language.
<IfModule mime_module>
AddHandler application/x-httpd-ea-php56 .php .php5 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit

Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteRule ^/?([a-z0-9]+)\.html$ /$1/ [R=301,L]

DirectoryIndex index.html index.htm index.php

说明:

  1. 第 10 行打开改写功能。
  2. 第 12 行是改写规则。它查找匹配正则表达式 ^/?([a-z0-9]+)\.html$ 的字符串,并将它替换成 /$1/$1 表示前面的正则表达式中用圆括号括起来的部分所匹配到的内容,R=301 表示 301 (永久)重定项,L 表示执行完此条规则后不再执行下面的改写规则。
  3. 此处的正则表达式详解:
    • ^ 表示从这里开始
    • / 就是左斜杠本身,它不是转义字符
    • ? 表示它前面的字符出现 0 次或 1 次,经测试此处必须有这个半角问号,否则匹配失败
    • () 用圆括号把正则表达式的一部分括起来,可以用 $n (n为从1开始的数字)表示圆括号里的正则表达式匹配到的内容
    • [a-z0-9] 用方括号把一组字符括起来,表示匹配之里面任意一个字符,此处的意思是任意一个小写字母(a-z)或者数字(0-9)
    • + 表示它前面的字符出现 1 次或多次
    • [a-z0-9]+ 表示至少1个小写字母或数字
    • \. 反斜杠和句点都是转义字符,因此如果要匹配句点,需要在它前面加一个反斜杠,所以说 \. 匹配 .
    • html 就匹配 html 这四个小写字母
    • $ 表示从这里结束

注意

  1. .htaccess 文件保存到 blog/sources/ 目录(此处假设我的博客源文件保存在 blog/ 目录里)。
  2. 在 macOS 系统中,默认把以句点开头的文件当作隐藏文件,所以需要按 Shift + Cmd + . 快捷键,让“访达”显示隐藏文件。

4.2 在 CF Pages 上配置 301 跳转

CF Pages 提供了文档[3],按照文档写一个重定向规则文件 _redirects 就可以啦。不过,比起 CPanel(Apache),CF Pages 几乎不支持正则表达式。

文件内容如下(只有一行)

1
/*.html /:splat/ 301

说明:

  1. * 号代表任意数量的任意字符,:splat 代表前文中的 * 号匹配到的内容。
  2. 301 代表 301 跳转。

注意:把 .htaccess 文件保存到 blog/sources/ 目录(此处假设我的博客源文件保存在 blog/ 目录里)。

4.3 配置 Hexo 使上述两个文件生效

两个文件

我虽然把 .htaccess_redirects 这两个文件放到了 blog/sources/ 目录,但是,如果不配置一下 Hexo,这两个文件是不会部署到远程主机的,也就不会生效[4]

用文本编辑器打开 _config.yml

  1. 找到 # URL 节,将 permalink: 的值改成 :abbrlink/ (注意前面的半角冒号和后面的半角斜杠)。让 Hexo 渲染生成的博客 URL 为不带 .html 后缀的 URL。

    permalink:

  2. 找到 # Include / Exclude file(s) 节,在 include: 下方添加上述两个文件名。让 Hexo 在渲染时将这两个文件也复制到 public/ 目录中。

    include:

  3. 找到 # Deploy 节,为每个远程主机添加一个新参数:ignore_hidden: false。让 Hexo 在部署时将作为隐藏文件的 .htaccess 也一并上传到远程主机。

    ignore_hidden

5 结语

搞定,301 跳转测试通过。


图片版权:

题图:"File:Symbol redirect vote2.svg" by Benoit Rochon is licensed under CC BY 3.0 .

头图:Image by Jose Antonio Alba from Pixabay

参考文献


求扫码打赏
“我这么可爱,请给我钱 o(*^ω^*)o”

用重定向去掉博文的 .html 后缀
https://blog.kukmoon.com/3366bd4a8b7d/
作者
Kukmoon谷月
发布于
2022年10月14日
许可协议