[分享] 增强个人网站的页面路径稳定性(预防404)且兼顾可读性

TL;DR 太长不看

如果你正在管理某个(内容分享向的)网站,为了从源头降低被引链接 404 的概率,我推荐尽早使用以下方案之一:

  • “我全都要”:Stack Overflow 式的 URL,兼顾 slug 的可读性与编号的稳定性,参见我所写的文章中的“编号与 slug 的真正结合”。
  • “够用就行”:经典的编号式 URL,参见此文,或我所写的文章中的“URL 与编号”。
  • “我不满意”:其他合理方案(欢迎补充)。

背景

很早之前,我就已经注意到,

  • 在阅读网络上的一些文章时, 其中引用其他文章的链接只要涉及到个人网站, 就时常会遇到链接失效(404 Not Found)的问题。
    • 这不仅是在引链失效的层面上降低了原文的时效性,
    • 也使我们难以做进一步的参考阅读。
  • 这样的引链也可能出现在你的笔记或收藏夹里,使得你很难再次溯源。

但是,除了部分文章真正被删掉的,或者域名移动/网站关停了的,其实有相当一部分链接所对应的文章实际上依然存在,只是 URL 路径改变了。——这本来是可以避免的。

本贴讨论方向

除了被引网站,其他有关各方也都有在一定程度上预防/解决 404 的策略,比如:

  • 读者可以利用 Org-mode 或 SingleFile 等工具来离线保存网页内容。
  • 含有引用链接的网站,则可以定期检测目标链接是否仍然有效,有条件的也可以保存被引用页面的快照。

不同的方向,解决的是不同的细分问题,故无法完全替代彼此。

而本贴的讨论方向聚焦于源头(被引网站)一侧,强调的是在线资源的路径稳定性:

作为被引用链接的网站,如何管理站内各页面的路径来预防 404?

为了防止歪楼,大家如果想要讨论其他方向的,请另开新贴,谢谢。

例子

以下随便找了一些“路径 404 但文章还在”的例子。

  • 在这篇文章中:
    • 404 的引链:
      • https://manateelazycat.github.io/emacs/2020/04/02/org-font.html
    • 引文的有效链接:
      • https://manateelazycat.github.io/2020/04/02/org-font/
  • lujun9972/emacs-document 中:
    • 404 的引链:
      • https://www.feoh.org/2015/07/15/vim-versus-emacs-minus-the-religion
    • 引文的有效链接:
      • https://www.feoh.org/posts/vim-versus-emacs-minus-the-religion
    • 注:这个仓库对引文做了快照,虽然影响溯源,仍然可以正常地阅读参考。

即使引链指向同一站点也并不能幸免,比如

  • 在这篇文章中:
    • 404 的引链:
      • https://www.wenhui.space/post/about%5Femacs/emacs%5Fpackage%5Finstall/
    • 引文的有效链接:
      • https://www.wenhui.space/docs/02-emacs/emacs_package_install/
  • @manateelazycat 的这篇文章中:
    • 404 的链接:
      • https://manateelazycat.github.io/2023/05/13/eaf-browser-html5-video.html
    • 引文的有效链接:
      • https://manateelazycat.github.io/2023/05/13/eaf-browser-html5-video

参考方案

这方面的规划属于网站组织设计的逻辑底层,最好尽早稳定下来。 因此早在几个月之前,我规划自己博客的那段时间,就已经在考虑这个问题。

当然,我并不是第一个考虑这个问题的人。比如:

  • 懒猫的这篇 Jekyll 定制文章链接 改进了 jekyll 将 :categorites 这种不够稳定的字符串加入到路径的默认链接配置。注:这是一个非常有限的改进,这里不作推荐。
  • Hugo 永久链接 - Ramen's Box :经典的编号式路径,即使文章本身发生较大改动也能维持路径不变。

各种 URL 路径的管理方案都有它们的优缺点。

  • 比如 Hugo 的常规配置就是目录树加 slug 组成的路径,这比较类似于我们的文件夹(可嵌套)与文件的形式,也易于理解;其缺点是,一旦文章发生变动就可能使原路径不再适应文章,此时要么变更路径(原路径 404),要么不变(继续脱节)。

所以为了在预防 404 的总体目标下,为了尽可能提升链接管理的综合质量,我也进行了大量观察/思考/设计/试验。

最近我将思路与收获整理出来,得到的是这样一篇文章:

此文并不是唯一答案,不过我已经尽力考虑到了我能想到的各种细节。 水平有限,仅作抛砖引玉。

如果你正在管理某个(内容分享向的)网站,请尽早关注站内 URL 路径的规划设计,以便降低引用它的链接在未来 404 的可能性。

这里并不是要把“预防 404”作为任何强制标准。只是,如果作为站长/管理员,我们能尽早为网站规划好一种稳定的 URL 路径设计,就能让网页中、收藏夹内、你的笔记里的大量引用链接的 404 概率更小一些,进而让互联网上由海量资料、链接之间形成的“知识星系”更加稳定易用,从而让我们的网络生活更加美好。

3 个赞

需要单独指出,“永久链接”(简称“永链”)并不意味着真正的“永久”。

它其实就只是网页的固有 URL 而已,区别于某些内容平台广泛使用(或者说滥用)的短链接或临时链接。

如果一个网站的 URL 路径规划稳定性不佳,这些“永链”很可能在后续变动中纷纷 404(一般来说,越是高产的博客就越是重灾区,比如懒猫的那个)。

我以前也想兼顾可读性的,后来被标题党轰炸了一段时间,就感觉文章标题或路径和内容之间没必要直接联系了,只要把搜索功能做好就行.

现在用的是: 时间戳-内容hash, 这样感觉很长,然后我把32位md5改成用16位的fnv1a64,但感觉还是长,然后又把时间戳和fnv hash转base58或者base64,这样不超过20个字符,路径够短了,当然还是比不了直接用编号最短

hash值是可以截断的,不需要考虑使用某种结果位数较短的算法。

此外,我实现的那个兼顾的方案是可长可短的。

比如 https://css.celestialy.top/p/feda224a0 这个链接就会重定向到固有链接:

https://css.celestialy.top/p/feda224a0/website-link-management-prevent-404/


并且,假如固有链接改成 https://css.celestialy.top/p/feda224a0/website-link-management-guide ,则旧的固有链接会重定向到新的固有链接。

文中实现的“编号与 slug 联合方案”具有一定兼容性。

  • 如果你正在使用纯编号 URL 的方案,可以无缝过渡到 Stack Overflow 式的“我全都要”方案。
    • 比如,我的博客之前采用的路径格式 /portal/xxxxxxxxx 目前也仍然有效,它会自动重定向到正确的路径比如 /p/xxxxxxxxx/foo1-foo2-foo3

此外,它对平台的适应性很强。

  • 只要是支持自定义 404 页面的托管平台,都能使用这个方案。
  • 生成静态站点的工具链,理论上也并不局限于 Hugo,因为它的实现只涉及 404 页面的 Javascript,再加一个从 /p/xxxxxxxxx/p/xxxxxxxxx/foo1-foo2-foo3 的 alias 重定向。

(似乎确定目录结构然后一直不变且在导出时保留原结构就可以了

(顺带,博客页面的目录似乎在亮色主题下可读性不是太好)

这就是问题所在了:404 的原因之一,正是目录结构的变化。

比如一楼举的例子 /post/about%5Femacs/emacs%5Fpackage%5Finstall 变为 /02-emacs/emacs_package_install

如果一开始没有做好路径设计,那么在后来发现博客的目录结构不适应新的内容,想要调整的时候,就有两种选择:

  • 改变目录结构,这样会导致原链接 404。
  • 如你所言,不改变目录结构——这样会导致它不再适应新的内容。

而如果一开始就做好路径设计,就能让目录结构与页面 URL 脱耦合,从而能在不导致 404 的前提下自由调整目录。

除了目录的变化以外,slug 或者说标题也是同理。


感谢反馈,这个问题的出现似乎与窗口宽度有关。我会尝试修复。(更新:已修复)

如果只是挂个静态 blog 的话确实得考虑下这样的设计。

不过如果能配置下服务器处理下旧的 URI 引向新 URI 也能行就是了。

(总之还是时间问题

1 个赞

一般都会有 permanent id,和 slug 结合起来,URL 大概是 /type/id[-/]slug,可以通过 url rewite 或者 pattern matching 直接取到 id,不会用到 slug。所以 slug 改变不影响 URL 的正确性。

你说的 permanent id 应该就是我所说的编号。

至于 url rewrite 和 pattern matching,应该就是我的方案中在自定义 404 页面中用 Javascript 所实现的那个功能。

既然你都把这两个当作似乎很常用的概念来这么说了,我想,你应该是指服务器端(比如 nginx)或内容托管平台(比如 netlify)所实现的功能?

不过,我所实现的方案是不挑服务器/内容托管平台的,只要能自定义 404 页面,理论上就一定可以使用。

上面说的: 时间戳-内容hash, 我开始设想的也是中间截断, 时间戳不是精确到秒或分钟, 是精确到天, 比如2024-5-13的是16进制时间戳是: 4d90,即1970-1-1到2024-5-13过去的天数。

然后 //blog.域名.top/4d90 这样就列出2024-5-13下所有文章, 文章的路径在补齐截断的hash,如果2024-5-13这天就只有一篇文章,就不用列出来了,也不用补齐路径, 直接跳转, 这个方案也设想很久了,但可惜我至今还没能实现

这种方案如果不从服务器/托管平台考虑的话,应该就是用 Javascript 来处理了。

不过我记得你是用 Org 作为“网页”?这样的话能自动执行 Javascript 吗?

我是用的php, 配置web服务器404页面指向 routh.php,在这个文件里面写javascript放<script></script>里面也可以。

继续看这个同时兼顾可读性与稳定性的方案,感觉和磁力下载比较像.

比如这个磁力地址: magnet:?xt=urn:btih: addr_hash &dn=标题 &tr=预防失效地址1&tr=防失效地址2

其中的标题部分是为了加强可读取性, 可以自由修改, 通常为防止地址失效会带有trackerslist, 这个和你说的稳定性(预防404)感觉也是一个意思

1 个赞