- 后端
- 文档
【免费下载链接】readthedocs.org
The source code that powers readthedocs.org
当你在项目中弃用一个功能时,往往也需要同步处理它的文档:既希望用户不再阅读这些内容,又不想让保存了旧链接的用户撞上 404。Read the Docs 提供了一套"渐进式、非破坏性"的内容弃用方法——从隐藏整个版本、给页面降权,到建立重定向,每一步都可以在保持旧链接可用的情况下逐步推进。本文基于 docs/user/guides/deprecating-content.rst 展开,并结合仓库源码说明底层实现,读完你将掌握一套可落地的内容弃用方案。
为什么"直接删除"不是好方案
弃用内容听起来就像删除它一样简单,但直接删除会带来两个问题:
- 破坏已有链接:用户、外部站点和搜索索引中可能保存了大量指向该页面的链接,删除后这些链接全部变成 404,体验非常糟糕;
- 内容也许不该彻底消失:你未必想让旧内容完全不可访问,可能只是希望它"不显眼"、不出现在搜索结果中。
Read the Docs 的思路是分阶段推进:先用隐藏/降权让旧内容淡出,一段时间后再用重定向接管旧链接。这个策略与 docs/user/user-defined-redirects.rst 中"不管理 URL 结构,用户迟早会遇到 404"的警告一脉相承。处理 URL 结构、重命名和删除内容的更多最佳实践,可参考 docs/user/guides/best-practice/links.rst。
弃用整个版本:隐藏 Version
如果你的项目有多个版本,文档也应当跟着版本化。假设你有以下三个版本,希望弃用 v1:
https://project.readthedocs.io/en/v1/https://project.readthedocs.io/en/v2/https://project.readthedocs.io/en/v3/
对这种场景,可以用隐藏版本(Hidden version)的方式处理。
隐藏版本的效果
- 隐藏版本不会出现在文档的版本菜单(flyout menu)中;
- 隐藏版本会被写入自动生成的
robots.txt,以阻止搜索引擎展示该版本的搜索结果; - 用户仍然可以通过直链访问隐藏版本的文档(隐藏不等于私有);
- 项目 Dashboard 中依然可以看到所有版本。
隐藏版本的完整状态定义见 docs/user/versions.rst 的 "Version states" 一节:
- Active / Inactive:Inactive 版本的文档内容会被删除,且无法触发构建;
- Hidden / Not hidden:Not hidden 版本会出现在 flyout menu 和搜索结果中;Hidden 版本两者都不出现,但任何拿到链接的用户仍可访问——隐藏适合"不再支持但不想移除文档"或"尚未准备好发布"的场景;
- Public / Private(仅商业版):Private 版本对无权限用户返回 404。
操作步骤
进入项目,点击Versions>Edit,勾选Hidden选项即可。隐藏版本的robots.txt行为在源码中有明确实现:在 readthedocs/proxito/views/serve.py 的_get_hidden_paths中,会筛选出所有hidden=True的公开版本,并通过Resolver.resolve_path计算出它们的绝对路径,随后在默认robots.txt中以Disallow: /path/to/version/的形式列出。这与 docs/user/reference/robots.rst 中"默认 robots.txt 会隐藏设置为 Hidden 的版本"的描述一致。
版本弃用与 semver 联动
如果你的版本号遵循 semver 规范,还可以为项目开启version warning notifications(版本警告通知)选项:凡是低于 stable 版本的文档页面上都会出现一条横幅,提示用户当前版本已过时,并引导他们跳转到 stable 版本。该通知由 Read the Docs Addons 提供,具体触发逻辑见 docs/user/versions.rst 的 "Version warning notifications" 一节:当展示的不是stable版本且存在stable版本时显示非稳定版通知;当展示latest且存在未隐藏的活跃stable版本时显示最新版通知。
从源码看,Read the Docs 会基于packaging与bumpver解析版本号以确定stable:readthedocs/projects/version_handling.py 中的determine_stable_version会先按版本号降序排序,剔除预发布版本(pre-release),并优先选择 Git tag 而非分支作为 stable 版本。
弃用单个页面:页内警告 + 搜索降权
并非每次弃用都涉及整个版本,有时你只想弃用某些页面。例如你的文档包含两套 API 文档,现在要弃用 v1:
https://project.readthedocs.io/en/latest/api/v1.htmlhttps://project.readthedocs.io/en/latest/api/v2.html
第一步:在页面顶部加警告
最简单的方式是在页面顶部添加一条警告(warning),告诉访问者该页面已弃用。但注意:这只提醒了直接访问页面的用户,并不能阻止用户从搜索引擎结果中被引导到这个页面。
可以利用 Sphinx 的 directives(如warning、deprecated、versionchanged)或 MkDocs 的 admonitions 来生成这类警告,例如:
.. deprecated:: 1.0 该 API 已弃用,请使用 v2 版本。第二步:在自定义 robots.txt 中屏蔽该页面
要让搜索引擎不再展示该页面,可以在项目的自定义robots.txt中为该页面添加Disallow条目:
# robots.txt User-agent: * Disallow: /en/latest/api/v1.html # Deprecated API关于robots.txt的实现细节,readthedocs/proxito/views/serve.py 中的ServeRobotsTXTBase视图说明:自定义robots.txt取自项目的default version(因为robots.txt需要在域名顶层提供服务,必须选择一个版本作为来源);若 default version 为私有、未激活或未构建,则返回 404;若 default version 中没有用户自定义的robots.txt,则渲染默认模板。默认模板内容见 readthedocs/templates/robots.txt,其中会列出隐藏版本的路径并包含sitemap.xml地址。生成robots.txt的方式因文档工具而异:Sphinx 通过html_extra_path配置将静态文件加入最终 HTML 输出;MkDocs 则要求robots.txt位于docs_dir目录下(详见 docs/user/reference/robots.rst)。
需要说明的是,robots.txt只被大多数搜索引擎"尊重"而非"强制执行",搜索引擎可能忽略它并仍然索引你的页面。如果文档必须绝对私有,请参考 docs/user/commercial/sharing.rst 的分享/权限方案。
第三步:通过 search.ranking 降低页内搜索排名
即使屏蔽了搜索引擎,你的文档站内搜索(server-side search)仍然会返回该页面的结果。Read the Docs 允许通过配置文件search.ranking为每个页面设置自定义排名。在项目根目录的.readthedocs.yaml中添加:
# .readthedocs.yaml version: 2 search: ranking: api/v1.html: -1这不会隐藏该页面的结果,但会把结果排在其他页面之后,从而降低旧内容被点击的概率。search.ranking的完整语法见 docs/user/config-file/v2.rst 的search小节:
- 类型:
map(模式到排名的映射),默认{}; - 匹配目标:构建产出的 HTML 文件的相对路径,例如匹配
index.html而不是docs/index.rst或/en/latest/index.html; - 特殊字符:
*匹配任意内容(含斜杠)、?匹配单个字符、[seq]匹配字符集合; - 取值范围:
-10到10的整数(含端点)。越接近-10排名越靠后,越接近10排名越靠前,0表示"正常排名"而非"无排名"; - 规则:多个模式匹配同一页面时,以最后匹配到的模式为准;官方建议降低要弃用页面的排名,而不是抬高其他页面的排名。
一个更贴近实战的示例(同样摘自配置文档):
version: 2 search: ranking: # 匹配单个文件 tutorial.html: 2 # 匹配 api/v1 目录下的所有文件 api/v1/*: -5 # 同时匹配根目录与嵌套目录下的 guides.html 'guides.html': 3 '*/guides.html': 3此外,search.ignore可以从搜索索引中完全排除某些路径(默认排除search.html、search/index.html、404.html、404/index.html),被匹配的页面不会出现在任何搜索结果中——如果你的弃用页面确实希望"彻底消失"于站内搜索,这是比降权更彻底的选项。
移除与移动页面:用重定向保住旧链接
当某功能弃用了一段时间后,你可能想彻底删掉它的文档——这完全合理,你不需要永远维护那些内容。但请记住:用户可能保存了指向该页面的链接,直接让他们看到 404 会非常沮丧和困惑。
解决方案是为旧页面创建重定向,指向具有相似功能或内容的页面。例如把弃用的 API v1 文档重定向到 v2 文档,即从/api/v1.html到/api/v2.html的page redirect(页面重定向)。
页面重定向(Page Redirect)
页面重定向作用于所有版本的文档,From URL不需要包含/en/latest之类的语言/版本前缀,只需要页面路径:
Type: Page Redirect From URL: /api/v1.html To URL: /api/v2.html访问https://project.readthedocs.io/en/latest/api/v1.html和https://project.readthedocs.io/en/stable/api/v1.html都会被重定向到对应版本的/api/v2.html。
精确重定向(Exact Redirect)
如果你只希望重定向某一个具体版本/语言下的页面,则使用精确重定向,From URL需要包含完整的语言和版本前缀:
Type: Exact Redirect From URL: /en/latest/api/v1.html To URL: /en/latest/api/v2.html典型的版本弃用场景是:把旧版本2.0(/en/2.0/)的读者引导到新版本3.0(/en/3.0/),可以使用通配符一次覆盖整个版本:
Type: Exact Redirect From URL: /en/2.0/* To URL: /en/3.0/:splat*为后缀通配符(仅支持后缀通配,不支持前缀和中间通配),匹配到的部分可通过:splat占位符引用到To URL中。注意:要让该重定向生效,旧版本必须处于**禁用(inactive)**状态;如果旧版本仍然活跃,则需要勾选Force Redirect选项。用户定义重定向的完整限制与示例见 docs/user/user-defined-redirects.rst,其中还包括用Force Redirect把/security.html的所有版本强制跳转到latest版本、以及目录级重定向/api/*→/api/v1/:splat等实战用法。
弃用策略总结:渐进式推进的三个阶段
| 阶段 | 目标 | 手段 | 效果 |
|---|---|---|---|
| 阶段一:版本级弃用 | 让整个版本淡出 | 隐藏版本(Hidden)+ robots.txt 屏蔽 | 版本菜单不展示、搜索引擎不索引,直链仍可访问 |
| 阶段二:页面级弃用 | 让单个页面淡出 | 页内警告 + 自定义 robots.txt +search.ranking降权 | 访问者看到警告、站内站外搜索排名靠后 |
| 阶段三:移除与迁移 | 彻底删除内容但不留 404 | 页面重定向 / 精确重定向(必要时 Force) | 旧链接平滑跳转到新页面,用户体验无损 |
这套流程的核心原则是:弃用是过程,不是删除动作。先用"隐藏"和"降权"降低旧内容的可见性,观察一段时间后再用"重定向"接管旧链接,最后才让内容下线——这样既能逐步引导用户迁移,又能保证已有链接不失效,是值得在文档维护中长期采用的非破坏性策略。
- 后端
- 文档
【免费下载链接】readthedocs.org
The source code that powers readthedocs.org
相关推荐
Qbot 回测绘图报 AttributeError: unexpected attribute 'plot_width' to figure 怎么处理?
Qbot 回测绘图报 AttributeError: unexpected attribute 'plot_width' to figure 怎么处理? 在 Q
后端文档终极Read the Docs容器化部署指南:Docker和Kubernetes完整教程
终极Read the Docs容器化部署指南:Docker和Kubernetes完整教程 Read the Docs是一个强大的开源文档托管平台,能够帮助开发者
后端文档Read the Docs 重定向系统设计:从五种重定向类型到 `*` / `:splat` 新语法与源码实现
Read the Docs 重定向系统设计:从五种重定向类型到 / :splat 新语法与源码实现 本文基于 Read the Docs(下称 RTD)的设计文
后端文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考