后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载本文基于 Read the Docs 的设计文档 In-doc search UI 展开完整解读“边输入边搜索”search as you type功能的设计目标、前端主题无关架构、后端 Elasticsearch 候选方案的优劣对比以及里程碑规划并结合当前仓库中 搜索 API v3、doc-embed 前端注入脚本 等源码说明这一设计最终在 Read the Docs 中的落地形态。读完本文你将理解一个面向数千个第三方主题的“主题无关”搜索 UI 该如何设计以及前端事件流、ES 分词器选型、特性开关Feature Flag在这一功能中的具体作用。一、背景为托管文档提供即时的搜索体验Read the Docs 托管了大量 Sphinx 文档让读者能快速找到所需信息是其核心诉求之一。设计文档的开篇即说明了出发点平台已经升级到最新版本的 Elasticsearch计划为所有托管文档实现 “search as you type” 能力——用户在搜索框中一开始输入就立即获得建议结果并以简洁、极简的前端呈现该设计是一个 GSoC 2019 项目文档本身即是对该功能的详细设计说明。原文明确标注了一个警告框本设计文档描述的是尚未实现的未来功能原文写作时点。需要说明的是该文档定稿于 2019 年其“未实现”的状态仅指当时的时间线。从当前仓库看search-as-you-type 能力后来以“搜索弹窗search modal”等形式落地本文第四节会给出仓库内的实现证据。理解这一点可以把本文当作“设计思路 后续演进”来读而不是孤立的历史文档。原文还引用了一个演示动图/_static/images/design-docs/in-doc-search-ui/in-doc-search-ui-demo.gif但该文件已不在当前仓库的图片目录中docs/_static/images/design-docs/ 下目前仅有 flyout 相关截图因此本文不插入该图。二、目标与非目标Goals and Non-Goals设计文档给出了清晰的目标边界这是整个方案可行性的前提项目目标支持 search-as-you-type / 自动补全界面——核心功能目标兼容所有或几乎全部Sphinx 主题——Read the Docs 上各项目使用各自主题的搜索框UI 必须“主题无关”theme agnosticJavaScript 体验向下兼容到 IE11无法支持时优雅降级graceful degradation项目维护者需要能够显式开启opt-in或关闭opt-out该功能——这是平台级功能的基本礼仪可选允许维护者通过自定义 CSS / JS 文件调整部分样式保留定制自由度。非目标首期只面向 Sphinx 文档原因是 Read the Docs 并未把 MkDocs 文档索引进 Elasticsearch 索引。这条非目标直接界定了首期范围——任何依赖 ES 索引的行为都不覆盖 MkDocs 站点。三、现有搜索实现基础设计并非从零开始。文档指出平台已有详细的服务器端搜索Server Side Search架构说明包括如何把文档索引进 Elasticsearch详见 Server side search。该文档同时列出了平台搜索的既有能力例如跨子项目subprojects搜索按文档标题/章节索引命中结果直达具体小节通过 配置文件 的search配置项自定义排序search.ranking、开关搜索弹窗等平台搜索无结果时回退到项目内置的 Sphinx 搜索。这些既有能力构成了 in-doc search UI 的地基前端只需对接已有的搜索 API重点解决“即时性”与“跨主题呈现”两个新问题。搜索语法与 API 的完整说明见 server-side-search/syntax 与 server-side-search/api。四、前端设计主题无关的 vanilla JS 方案4.1 技术选型前端要求“主题无关”因为每个托管项目可能使用任意的 Sphinx 主题。设计文档说明团队探索过多个第三方库但没有一个完全满足需求因此倾向于使用 vanilla JavaScript原生 JS实现其相对第三方库的优势是对 DOM 有更强的控制力性能收益无额外库开销。4.2 交互架构原文给出的实现路径是利用 JavaScript 的querySelector()选中“每个主题都存在的搜索框”为其添加事件监听器监听输入变化change/input 事件一有变化就向平台后端发起搜索查询后端返回建议suggestions用document.createElement()和node.removeChild()动态创建/移除节点刻意避免在 DOM 中留下空的div残留。这套“监听输入 → 请求 API → 动态渲染建议”的链路正是典型 search-as-you-type 客户端模式对后端的要求是低延迟、可高频调用这一点对第六节的后端选型至关重要。4.3 CSS / JS 的分发方式文档列出了把所需 JS/CSS 注入到所有托管项目的三种候选方案直接写入现有 embed 文件把 CSS 加进readthedocs-doc-embed.css、JS 加进readthedocs-doc-embed.js随现有机制自动包含。当前仓库中确实存在这类分发文件例如 readthedocs-doc-embed.jswebpack 打包后的产物与 readthedocs-doc-embed.css独立打包把 in-doc search 打包成自包含的 CSS/JS 文件以与readthedocs-doc-embed.*类似的方式引入打包成 Sphinx 扩展按项目粒度开启最方便准备向更大范围推广时可以再决定是“默认全量开启”还是“像 404 扩展sphinx-notfound-page那样作为 opt-in 功能”提供。4.4 仓库现状佐证doc-embed 如何接管 Sphinx 搜索从当前仓库的 readthedocs-doc-embed.js 源码结构看embed 脚本的 search 模块已经实现了“主题无关接管搜索”的完整模式可以印证上述设计思路的实际落地通过window.READTHEDOCS_DATA获取project、version、language等运行时数据并检测docsearch_disabled特性开关对应目标 4 的 opt-out 能力仅在 Sphinx 构建器is_sphinx_builder()上启用MkDocs 项目打印 “Server side search is disabled.”——与设计文档“首期仅 Sphinx”的非目标一致劫持 Sphinx 主题暴露的Search.query全局函数保存原函数为Search.query_fallback替换为调用平台搜索 APIproxied_api_host /api/v2/search/?q...project...version...的异步 fetch请求失败或无结果时回退Search.query_fallback即项目内置的 Sphinx 搜索结果渲染使用document.createElement生成li/a/div.context等节点对highlights字段做 XSS 防护SafeString包装 innerHTML并给高亮span统一加highlighted类——正是设计文档中“动态创建/移除节点、高亮匹配词”思想的实现。这说明前端侧的设计主题无关、劫持既有搜索入口、高亮渲染、优雅回退已经完整进入生产代码只是交互形态从“搜索框下方建议列表”演进为下一节所述的搜索弹窗。五、UI/UX两种建议呈现方式文档给出了展示建议的两种交互方案搜索框下方下拉建议传统 autocomplete 形态点击搜索字段时打开全屏full page搜索界面。从仓库现状看Read the Docs 最终采用的是方案 2 的变体Server side search 的 “Search as you type” 一节描述了当前产品形态——搜索弹窗支持边输入边出结果并保存最近搜索用户按/键即可唤起。是否选择全屏界面还涉及目标 2兼容所有主题下拉方案更容易被各主题的布局z-index、容器裁剪、响应式破坏全屏/弹窗方案的 DOM 挂载点可控性更强。原文并未给出最终结论属于“可以推断”的演进方向。六、后端设计两种 ES 候选方案对比search-as-you-type 对后端的本质要求是高频、小查询量下仍能低延迟返回“前缀/部分前缀匹配”的建议。文档对比了 Elasticsearch 的两种机制6.1 Edge NGram Tokenizer边沿 n-gram 分词器优点缺点对“可能以任意顺序出现的单词”做自动补全时比 Completion Suggester 更有效需要更大的磁盘空间相当快大部分工作在索引时完成自动补全耗时低支持对匹配词做高亮highlighting6.2 Completion Suggester完成建议器优点缺点为速度优化非常快匹配总是从文本开头开始Hel能匹配Hello, World但匹配不到World Hello不需要大磁盘空间不支持匹配词高亮官方文档指出快速查找的构建代价高且数据保存在内存中两者的核心取舍可以概括为Edge NGram 用磁盘换“任意位置前缀匹配 高亮”Completion Suggester 用“仅词首匹配”换低开销但其 in-memory 特性在大索引下反而是内存隐患。文档将其列为开放问题之一见第九节没有在此下定论。6.3 仓库现状佐证搜索 API v3 与特性开关设计文档中“Is our existing Search API sufficient?”的开放问题在当前仓库中已有了明确答案——专门的 Search API v3readthedocs/search/api/v3/views.py 定义了SearchAPI视图其类注释明确指出该 API “会被匿名用户以及我们的 search-as-you-type 扩展使用因此需要提高限流阈值”限流设置为100/minute匿名与已认证用户各一个 throttle见 views.py。这直接回应了前端“每次输入变化都发请求”的高频调用场景视图强制q查询参数响应额外携带projects与最终query字段views.py并对响应打 cache tag项目 slug 版本 rtd-search索引标签保证文档重建或索引更新时缓存被清除views.py查询执行前有特性开关判断readthedocs/search/api/v3/utils.py 的should_use_advanced_query()通过项目特性Feature.DEFAULT_TO_FUZZY_SEARCH定义于 readthedocs/projects/models.py决定该用哪种查询策略。这一 Feature 机制正是设计文档目标 4维护者可 opt-in/opt-out在平台层的工程实现方式前端侧的 API 契约见 server-side-search/apiGET /api/v3/search/接受q、page、page_size默认 50参数返回分页结果每条含highlightsHTML 转义、匹配词包在span中与blocks可锚定到具体小节的 section 块——“高亮匹配词”这一 Edge NGram 的卖点在 API 层已是一等公民。此外从源码结构看search-as-you-type 的形态并不局限于文档阅读页readthedocs/projects/filters.py 中ProjectListFilterSet的 docstring 说明它同时为 Dashboard 项目列表提供 “search-as-you-type lookup filter”即平台自身的界面也在复用这一交互模式。而 CHANGELOG.rst 中 “Javascript client: search-as-you-type API response” 的变更记录也印证了 JS 客户端为 search-as-you-type 响应做过专门适配。七、里程碑Milestones设计文档附带了 GSoC 2019 时间线完整继承如下里程碑截止日期项目的本地实现2019 年 6 月 12 日在 Read the Docs 托管的测试项目上、基于 RTD Search API 实现 in-doc search2019 年 6 月 20 日在 docs.readthedocs.io 上实现 in-doc search2019 年 6 月 20 日友好的用户试用用户可在自己的文档中启用该功能2019 年 7 月 5 日对排名前 10 的 Sphinx 主题做额外 UX 测试2019 年 7 月 15 日UI 定稿2019 年 7 月 25 日改进搜索后端以获得高效、快速的搜索结果2019 年 8 月 10 日里程碑本身透露了两个设计要点一是先本地、再测试项目、再全站的灰度推广路径呼应 4.3 的分发方案讨论二是对 Top-10 主题做专项 UX 测试说明“跨主题兼容”被当作与功能本身同等重要的验收标准。八、开放问题Open Questions文档最后留下了四个未决问题它们也是后续实现走向的线索依赖 jQuery、第三方库还是纯 vanilla JavaScript从 readthedocs-doc-embed.js 当前仍是 jQuery 原生 API 混用的打包产物看仓库现状偏向渐进式原生 JS但保留 jQuery 兜底此为从源码结构看出的推断子项目subprojects是否要纳入搜索范围现有 Search API 是否足够由 Search API v3 的落地可以回答足够并按 search-as-you-type 的使用模式调整了限流与缓存采用 edge ngrams 还是 completion suggester九、小结这篇设计文档的价值在于完整呈现了一个平台级搜索 UI 的决策链路范围收敛首期只做 Sphinx非目标兼容所有主题目标IE11 优雅降级前端模式querySelector定位各主题的搜索框 → 监听输入 → vanilla JS 动态渲染建议并自动清理 DOM分发上优先复用readthedocs-doc-embed.*或做成可 opt-in 的 Sphinx 扩展后端取舍Edge NGram索引期开销、支持任意位置前缀与高亮、占盘大 vs Completion Suggester更快、占内存、仅词首匹配、无高亮可控性以特性开关让维护者 opt-in/opt-out这正是当前仓库中Feature机制与docsearch_disabled开关所体现的工程惯例。对读者而言这份“设计文档 仓库源码”的组合是一个很好的案例先读 docs/dev/design/in-doc-search-ui.rst 理解 why 与 trade-off再对照 Search API v3、doc-embed 脚本 与 Server side search 用户文档 理解 how 与 what shipped即可获得从设计意图到生产实现的完整视角。赞分享后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载相关推荐如何用Nix构建mermaid-asciiflake.nix可复现构建指南如何用Nix构建mermaid asciiflake.nix可复现构建指南 mermaid ascii 是一款能将 Mermaid 图表直接渲染为终端 ASCCLI开发工具Read the Docs Embed APIv3跨站点嵌入文档内容的设计方案与源码实现Read the Docs Embed APIv3跨站点嵌入文档内容的设计方案与源码实现 本文围绕 Read the Docs 的设计文档 embed api后端文档Read the Docs 文档 URL 解析设计从保留路径问题到 unresolver 的查找实现Read the Docs 文档 URL 解析设计从保留路径问题到 unresolver 的查找实现 本文围绕 Read the Docs 仓库中的设计文档后端文档上一篇BonMot调试与测试5个实用技巧提升开发效率下一篇G-Helper 完整指南免费替代 Armoury Crate性能模式与风扇曲线调校创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?