Skip to main content

· 9 min read
Yilin Zeng

背景信息#

Algolia DocSearch 是一个开源的搜索框,可以免费为其他开源软件或服务提供支持。在维护 Rancher 中文文档的时候,我碰到了一个 Algolia DocSearch 搜索框失效的问题。作为一个没有太多技术背景和代码经验的文档工程师,我花了很久才把这个问题搞清楚。后来在面试其他公司的时候,恰好他们也有这个问题,就提了个 issue,给了一些排查思路。面试都过了,但是最后 offer 审批慢了一些,就没去。这个问题在 Rancher 中文文档的代码库 wiki 里面也有记录,但当时图快,写得比较粗糙,还是希望静下来仔细写一下的。

问题现象#

  1. 通过 Rancher 文档页面的搜索框输入关键字进行搜索时,单击返回的链接,有一些链接会跳转到 404 页面。实际上这些链接是真实存在的,可以直接访问这些链接,但通过搜索框跳转访问就是不行。

  2. 只有一部分链接失效,另一部分链接是正常的。

排查过程#

这个问题是驻场 SE 报告的。在他驻场的那段时间里面,需要经常阅读官网文档辅助日常工作。由于 Rancher 中文文档的目录层级比较深,通过导航栏和目录找文档会耗费很多时间。所以他就用了搜索框输入关键字,找到他想要看的文档。

这个问题第一次出现的时间点是 2020 年 8 月,正好这段时间 Rancher 中文文档的网址在切域名,从 https://rancher2.docs.rancher.cn/ 切换到 https://docs.rancher.cn/。 切换域名之后,没有去更新 DocSearch 的配置信息,导致失效。去更新了之后,问题就解决了。

原本以为到这里之后,问题就结束了,但是 2020 年 11 月 这个问题又出现了,搜索框返回的 Rancher 2.5 文档链接失效。

解决问题#

有了上次的翻车经验,这次还是一样的处理方式:首先是把 8 月份客服帮忙解决问题的邮件回复翻了出来,找到他修改的代码和提交的 PR,照葫芦画瓢改一个再交上去。然后是跟现在对接的客服沟通,如何生成新的 sitemap.xml,所幸 DocSearch 提供了插件和详细的操作说明,操作起来也不太难。

在第一步的时候出现了一个小插曲:8 月份客服帮忙解决问题的邮件回复里面带着他提交的 PR 链接,而顺着链接找过去对应的代码库,找不到 rancher 对应的 rancher.json 文件。找过去之后我一度怀疑是不是找错了地方,直到发现最上方有一行小字:我们客户太多了,只能够显示前 1000 位客户的配置文件,按字母 a~z 排序,例如 a.json ...一直到 z.json,后面还有 2000 多位客户的配置文件无法在页面显示。

先 git clone 到本地看看再说,一看果然有 rancher.json 文件,上面配置的链接还是旧的,于是就把链接替换为新的,然后交了个 PR,等审核和合入。

然后在第二步的时候按照 DocSearch 提供的说明,首先在命令行界面 cd 到文档所在的文件夹,运行以下命令添加 sitemap 插件:

yarn add @docusaurus/plugin-sitemap

然后在docusaurus.config.js里面添加了以下代码:

plugins: [        [            "@docusaurus/plugin-sitemap",            {                cacheTime: 600 * 1000, // 600 sec - cache purge period                changefreq: "weekly",                priority: 0.5,                trailingSlash: false,            ,        ],

在第一步提交的 PR 合入 DocSearch 的 master 分支后,将第二步的修改合入到 Rancher 中文文档的 master 分支,上线生产环境之后,搜索框的问题就解决了。

复盘和回溯#

根据时间线来看,导致问题第二次的 PR 应该出现在 2020 年 8~12 月,涉及 docusaurus.config.js 的修改。8 月份有 1 个修改 docusaurus.config.js 的 PR,修改的原因是百度统计插件失效了,我们看 plugins 的时候发现没有百度统计插件,反而有一坨这个玩意。

plugins: [        [            "@docusaurus/plugin-sitemap",            {                cacheTime: 600 * 1000, // 600 sec - cache purge period                changefreq: "weekly",                priority: 0.5,                trailingSlash: false,            ,        ],

我们误以为它是没用的,就把这段代码删除了,替换为百度统计插件:

plugins: ["@docusaurus/plugin-baidu-analytics"],

此刻我们修复了百度统计插件失效的问题,同时在无意中引入了搜索框失效的问题。

根据问题现象来看,搜索框能够正常返回所有 8 月之前添加的文档页面,而 8 月份之后删除的页面不会消失,8 月份之后新增的页面不会显示。恰好也印证了上述的猜测。

也就是说,这段时间实际发生的事情是这样的:

2020 年 8 月:误删除搜索框相关代码,导致 8 月之后更新的文档和搜索框返回的结果对应不上。Algolia 客服在他们的代码库中修改了 Rancher 的网页链接,然后在 Rancher 搜索框里面试了一下,实测返回结果有效,则认为所有返回结果都有效,然后告诉我 it works now,那么我也认为 Algolia 官方的人是对的。实际上误删除相关代码之后只能通过重新插入代码才会让搜索框完全生效。

2020 年 9~10 月:新增和删除的文档信息无法同步至 Algolia。

2020 年 11 月:发现问题根因并重新插入代码,最后问题得以解决。

Algolia 的实现原理#

从邮件交流和实测结果看,Algolia 的实现原理是这样的:

  1. 时效性:每隔 24 小时爬取一次网站上面的所有链接,以获取在过去的 24 小时内网站的修改。换句话说,需要 24~48 小时之后,搜索框才会更新新增和删除的文档链接。具体的表现为:新增的文档链接需要 24~48 小时之后才会出现在搜索框的返回结果内,而删除的文档链接需要 24~48 小时之后才会从搜索框的返回结果消失。

  2. 需要在 docusaurus.config.js 添加配置信息才会生效。删除这些配置信息之后,已有的结果不会失效,但是 Algolia 不能获取到增量变化的文档和页面。具体表现为,一部分失效了,另一部分还是正常的。

aloglia rancher architecture

参考资料#

  1. 如何添加 Docusaurus sitemap 插件

  2. Algolia docsearch-configs

· 4 min read
Yilin Zeng

前情提要#

数据有助于我们分析和评估文档网站某一段时间的内表现,举个例子,跟第二篇博客联系起来:怎么知道修复完断链之后,文档网站的数据变好了呢?这个时候就需要用到数据分析工具了。

市面常用的数据分析工具有 Google Analytics 和 百度统计,恰好我两个都用过,也在 Google Analytics 上面踩过一些坑。作为工具 x 部曲中的第二部,今天来对比一下 Google Analytics 和 百度统计,并讲一讲为什么最终选择了百度统计。

我的需求#

无非就是需要一个监控工具嘛,那我当然希望这个监控工具满足我的需求咯。

  1. 简洁明了的仪表盘。

  2. 需要看到一段时间内网站各项基础数据的变化趋势。例如,浏览量、独立 IP 数等。这些可以很直观地告诉我,这段时间内访问量是不是上来了。

  3. 灵活和精细的时间颗粒度,便于对比每天、每周、每月的数据变化。

  4. 持久的数据储存,便于翻旧账。

  5. 需要展示每个网页的浏览量,这样我可以知道用户重点关注和阅读的内容,便于精确修改和完善这部分内容。

  6. 需要展示用户搜索的关键字,这样我可以为这些网页统一添加关键字并提升 SEO。

Google Analytics 的坑#

GA 的坑点有点多。首先是对于小白用户不友好,前置步骤我不会弄。其次是我想要的很多参数它没有,比如 top viewed、 关键字等等。最后是我的领导也不想用 GA,所以用了一段时间之后,我们就放弃了。当然不是在全盘否定 GA,只是在当时我所在的场景下,GA 确实不能满足我的所有需求。

百度统计的优势#

这里要夸一夸百度统计的本地化做得好,我想要的它都有。它的缺点是,只能存一年内的数据。

问题回顾#

回到问题本身,选择一个数据分析工具以监控 Rancher 中文文档网站的数据,我们在乎这个网站在哪个搜索引擎上的排名靠前?当然是以中国用户的习惯为准,百度优于 Google。那么选择 GA 作为百度优化的基础自然是不对的,至少不是最优选。所以我们最后选择了百度统计。

百度统计引发的问题#

百度统计在给我们带来方便的同时,也埋下了一个雷,放到下一篇博客再说了。

· 9 min read
Yilin Zeng

前情提要#

在我的第一篇博客最后,我给自己出了一份将来要更新的博客列表。拖更了两周,现在回来了。其实我想了很久要从哪里开始说起,想来想去,还是先从简单的开始吧。

背景信息#

什么是断链#

断链是网页上加了一个超链接,单击该链接跳转至另一个网站时,无法访问该网站,返回 404。

断链分两种:internal 和 external。internal 指的是站内跳转,external 指的是外部跳转。

产生断链的原因非常简单:链接失效了。导致链接失效的原因有很多。例如:结构层级变化、手动输入的时候输错了、页面下架了等等。

为什么要干掉断链#

谁都不希望在阅读产品文档的时候,点一个链接返回 404。在安装或快速入门这一类的文档中,开发者为了节省时间和精力,通常会将安装所需的依赖浓缩成一个个超链接。但是如果在这个时候,链接断了,相当于阻碍了新用户进行初步了解和入门,不仅体验感差,而且会流失新用户,降低产品口碑,问题非常严重。其次,搜索引擎会依据网页内的有效链接和断链数量对其进行评分,断链越多,评分越低,在搜索结果中返回的排名越低。

怎么干掉断链#

背景信息里面说了,产生断链的原因是链接失效了。这时候该怎么修复它们呢?以下是我常用的三个思路:

  1. 直接删除:如果自己判断这个链接是多余的,那就可以直接删掉,不用花时间找正确的替代了。

  2. 修改为正确链接:如果自己判断这个链接是有用的,那就需要自己去找正确的链接,排查的过程也非常简单,大部分都是结构层级变化或手动输入的时候输错了。

  3. 替换为其他链接:如果自己判断这个链接是有用的,但上一个步骤找了半天找不到正确的链接,那么可以换个思路:我找个替代品总可以吧?

为什么不用 GitHub 集成的 CI 工具做扫描?#

这个时候有人可能就要问了:GitHub Action 里面已经有各种官方和自制的 CI 工具,为什么不用它们去做这件事情呢?

原因无他,概况为三个字:局限性。

首先是 CI 工具自身的局限性:

  1. 只能在提交 pull request 的时候,那一刻没问题不代表接下来都没问题。

  2. 只能测当前 pull request 造成了哪些断链。

  3. 大部分只能测 internal,而不能测 external。

其次是我自己的局限性:如果要满足自己的需求,则需要一定的客制化代码开发,我不具备这个能力。

选型过程中碰到的问题#

由于 GitHub Action 和 我自身的局限性,我选择了另一条道路:Google 搜一下看看,不止我一个人有这个需求,肯定会有对应的产品解决我的问题。经过一些时间的搜索和尝试,我确实发现了几款工具,应该可以满足我的大部分需求。

  1. W3C Link Checker

  2. Online Broken Link Checker

  3. Link Alarm

  4. Web Link Validator

  5. Dr Link Check

工具各项属性对比#

名称成本准确性便捷性
W3C Link Checker免费中等,会有误报不方便,要自己洗数据
Online Broken Link Checker免费中等,会有误报不方便,要自己洗数据
Link Alarm免费中等,会有误报不方便,要自己洗数据
Web Link Validator免费中等,会有误报不方便,要自己洗数据
Dr Link Check收费,订阅制,$198 一年高等,会有误报方便,支持表达式过滤误报

试了一圈之后,最初锁定的是 Online Broken Link Checker,再加上 W3C Link Checker 作为后备项。两个工具同时挂掉的概率非常小,虽然要自己把数据导出到本地再清洗,但是它们绝对能够满足日常使用。

选择免费版工具的过程中踩了哪些坑#

Online Broken Link Checker 和 W3C Link Checker 的槽点也蛮多。

  1. 时间长,不够用户友好:空运行一次半小时起步,手抖不小心关了浏览器得重来。

  2. dry run 数据不一致:连续跑几次,返回的数据都不一样。

  3. 工具 service down:Online Broken Link Checker 曾经有一段时间不可用了,404 检测工具自己变成 404 了,还满讽刺的。幸好我准备了 plan B 哈哈哈。

  4. 数据清洗费时费力:原表格的排列和我想看的有出入,要自己导进去 Excel 再重新整理,非常耗时间。

  5. 不支持过滤误报:算是 dry run 数据不一致的副作用之一,我觉得可以有误报,但是不支持过滤就很烦了。

为什么最后选了 Dr.LinkCheck#

经历过 Online Broken Link Checker service down 一段时间之后,我决定还是得换个收费的工具试试看,就换到了 Dr.LinkCheck。因为 Dr.LinkCheck 的收费标准是分阶段的,超过 1000 个链接要收钱,超过 2000 个链接又要加钱。所以我综合了当前的链接数量和日后可能会新增的链接数量,选择了最便宜的包年订阅套餐。

Dr.LinkCheck 的优势#

  1. 数据更精准:对比下来它是最精确的。

  2. Dashboard 可视化:使用门槛低,在页面上点就行。

  3. 支持项目隔离:可以自己控制 scope,局部和全局都 ok。

  4. 不用自己做数据清理。

  5. 支持正则表达式过滤误报。

  6. 扫描在后台运行,与 UI 解耦,再也不用担心手抖误关页面了。

  7. 有客服有邮箱,回复还算快。

  8. 没事帮别人扫一扫,提个 pr 修问题刷脸。

Dr.LinkCheck 的缺点#

贵(可能是我的问题?)

使用 Dr.LinkCheck 达到了什么效果#

  1. Rancher 中文文档网站 0 断链。

  2. 自动化,设置双周扫描,有问题会发邮件。

  3. 解放生产力,再也不用花大块的时间盯着这个问题了。

  4. Impress 领导和同事。你们都没资源没时间干的事情,我搞定了。最后这个订阅费用也通过其他途径报销了,美滋滋。

后续计划#

加大力度,继续使用 Dr.LinkCheck。

· 6 min read
Yilin Zeng

前情提要#

前一篇博客有提到断链扫描工具的选型,最后我选择了 Dr.LinkCheck。这篇博客就简单说一说怎么使用这个工具吧。

免费扫描#

  1. 打开浏览器,输入 https://www.drlinkcheck.com/,访问 Dr.LinkCheck。

  2. 在文本框中输入你要扫描的网址,单击 “Start Check” 开始扫描。

  3. 根据返回结果修复链接。

tip

Dr.LinkCheck 的免费额度是 1500 个链接,如果网站的链接数量大于 1500,建议付费升级或使用其他工具。注意链接数不等于页面数,一个页面可以有 0 个链接,也可以有非常多的链接。如果非要粗略估计的话,总链接数 ≈ 总页面数 x 5 是一个比较合理的值。

付费扫描#

  1. 打开浏览器,输入 https://www.drlinkcheck.com/,访问 Dr.LinkCheck。

  2. 单击页面右上角 “Login”,进入用户登录页面。

    login

  3. 输入用户名和密码,单击 “Login”,进入用户概览页。

    login page

  4. 单击 “rerun Check” 对已有项目进行扫描,或单击“add a project”添加新的项目并扫描。

    dashboard

  5. 根据返回结果修复链接。

进阶操作#

在已经成为付费用户的基础上,这些操作可以提升工作效率,节省碎片化的时间。

添加过滤条件#

总有那么一些链接是误报的,有两种过滤方式。

第一种,假装看不见,不处理。以后重复出现这种误报的结果可以直接挂在那里,选择性忽略掉它们。

第二种,使用正则表达式,添加过滤条件,重复出现的时候它们会被过滤掉,不出现在最终结果里面。

  1. 单击 “Project Settings”,打开项目配置页。

  2. 单击 “Advanced Settings”,展开高级配置项。

  3. 找到 “Ignore links if...” 这一项,并在文本框中输入你的过滤条件。

    settings

  4. 重新运行扫描,查看扫描结果是否符合预期,如有需要可以进一步修改和完善你的过滤条件。

tip

Dr.LinkCheck 的官方文档中有详细讲述如何配置表达式,详情请见 Dr.LinkCheck Documentation

举个例子,这是我为 Rancher 中文文档网站配置的过滤条件。

Url STARTSWITH "https://git.rancher.io" OR Url STARTSWITH "https://keycloak.org/docs" OR Url STARTSWITH "http://xip.io/" OR Url STARTSWITH "https://docs.vmware.com" OR Url STARTSWITH "https://www.splunk.com"

可以看到我只用了两个变量 Url STARTSWITHOR,就把误报的过滤掉了。建议从你想要的效果出发,去文档里面找能够满足这个效果的一个或多个过滤条件。如果反过来,先把文档读完,里面的过滤变量太多,描述太详细,容易把自己的思路弄乱,反而不好。

项目隔离#

项目隔离是个好东西。从付费的规则讲起,我用的最便宜的付费版,限制是:

  1. 每个项目扫描的链接数量不超过 10000 个。

  2. 最多同时可以存在 5 个 项目。

在这些规则限制内,我能玩出什么花活?

  1. 理论上我可以扫描的链接数量是 5*10000 = 50000 个。在一个项目的链接数超出 10000,或者我想要精确扫描某一个部分的时候,我可以创建新的项目,满足我的需求,而且用完可以立马删除。

  2. 帮其他开源项目扫描,提交 pr 修复这些问题。

自动化#

自动化也是个好东西。Dr.LinkCheck 支持每两周自动执行所有项目,并结果发送至指定邮箱。从初期解决完所有断链之后,我只要每两周抽一个上午出来处理这些问题即可,美滋滋。

  1. 单击 “Project Settings”,打开项目配置页。

  2. 找到 “Run biweekly > on Monday - at about 08: 00” 这一项,并在调整自动化扫描周期。

  3. 找到 “Email results of recurring check to...”,并在文本框中输入邮件地址。

    settings

  4. 查看扫描结果是否符合预期,如有需要可以进一步修改和完善你的定时扫描计划。

总结#

Dr.LinkCheck 真好用,建议大家试试看,说不定能开发出其他玩法。

· 8 min read
Yilin Zeng

我是谁#

我是曾奕霖,GitHub ID:yzeng25,是一个拥有三年多工作经验的文档工程师,曾就职于华为、Rancher Labs(2020 年底被 SUSE 收购)和 API7.ai。

2018.11~2020.01,我负责华为云中间件 ROMA(后更名为 Roma Connect) 的用户文档写作,截止至目前,该项目的文档仍有 70% 的内容是我当时留下的。说人话就是:文章是我写的,图片也是我画的。

2020.02~2021.07,Rancher 2.x 中文文档的维护者。我作为 Rancher/SUSE 大中华区唯一一个文档工程师,我翻译和编辑了 Rancher 2.x 中文文档、翻译了 Rancher 2.5.3 和 Rancher 2.5.8 的 UI、对 Rancher 2.x 中文文档网站进行了 SEO 改造并使月均浏览量从 30000+次 上涨至 96000+次。除此之外,我还引入了一些便捷的工具以减轻工作量和简化工作流程,如断链扫描、百度统计等。我在这个代码库的贡献者中排名第一,commits 数量是第二名的 3 倍,修改的行数是第二名的 17 倍。如无意外,近一年内霸榜的应该还是我。

2021.07~2022.04,API7.ai 文档工程师,Apache APISIX 首个以文档工程师身份成为 Apache Committer 的人,纵观国内的 Apache 项目,以文档工程师身份成为 Apache Committer 的人只有四个,前两个在 Apache Pulsar,第三个是我,第四个是我在 API7.ai 的前同事,她的 git 命令都是我教的。 参与 Apache APISIX 博客网页设计,编辑、翻译博客文章,拓展 Apache APISIX 并成功与多个国内外知名社区展开联动。

2022.04~present,公司 B 轮融资玩砸了,喜提离职补偿,目前属于灵活就业。

自带行业冥灯 debuff。

从华为离职后,华为云中间件深圳资料团队大换血,最终被划到了一个很边缘的部门。

从 SUSE 离职后,半年多找不到人顶我的位置,恰好碰到大版本和新产品上线,现在属于是债多不愁了。

从 API7.ai 离职后,公司 B 轮没融到,不知道还能撑几年 hhh。

为什么要用 Docusaurus 做这个网站#

因为从 2020.02 到 2022.04,我一直在使用 Docusaurus。一方面是恰好两个公司都选择了这个框架,另一方面是这个框架简单易用,且拥有一个非常友好活跃的开源社区,提问题提 issues 都能在短时间内获得解答。

  1. 用魔法打败魔法,用 Docusaurus 写 我的 Docusaurus 踩坑指南,我觉得是一件很酷的事情。

  2. 技术大佬们都有自己的博客,我在全职打工的时候就想建一个自己的博客,但是在已有的博客平台上面写东西太逊了,既然 Docusaurus 这么好用,可以先拿它试试看,最坏的结果不就是删库嘛。

  3. 我在全职打工时候基本上就是碰到问题就去看文档、看 Google、看 Stack Overflow 帖子,面向问题开发文档。首先是只局限在了码字上面,其次是没有完整地、系统地了解过 Docusaurus 的框架和结构,这容易把路走窄了。所以这波我想试试水,把 Docusaurus 学明白,然后也把 Vercle 之类的部署和发布工具学明白。

  4. 坦白讲 Docusaurus 的中文文档比英文文档要差,既然我踩过坑,我就希望其他同行在碰到问题的时候能找到中文的文档来解决类似的问题,看英文文档确实会令人头大,特别是任务紧急的时候。我也有计划去参与 Docusaurus 的中文文档翻译,不过这至少是今年下半年的事情了。

  5. 提交 commits、合并 PR、发布博客可以改善我的 GitHub 活跃度。

未来打算更新的内容#

  1. Docusaurus 踩坑指南。

    1. 当时简单记录在 Rancher wiki 里面的一些问题和解决这些问题的思路。

      1. Algolia DocSearch 搜索框失效的排查及修复过程

      2. Algolia搜索框注意事项

      3. master分支和preview分支构建失败详解

    2. 参与 Apache APISIX 中英文博客编辑时碰到的问题和解决思路:Docusarus 的 i18n 工作机制和原理

  2. 我的常用工具和选型思路:

    1. 为什么要用付费工具 Dr.LinkCheck 为开源网站进行服务?

    2. 为什么要从 Google Analytics 转到 百度统计?

  3. 罗马不是一天建成的,开源文档也不是 -- 记录开源文档的养成阶段

    1. 从无到有。
    2. 从有到优。
    3. 聆听社区,积极回应。
    4. 让更多人看到你的文档。
    5. 学会取舍,聚焦用户在乎的文档。
  4. 拓展 Apache APISIX 生态时碰到的故事和事故:

    1. 大无语事件,生态合作聊到一半,创始人离职了怎么办?-- 记录 Dapr 合作
    2. 都什么年代了,怎么还有人在用 AsciiDoc 建站?-- 记录 Keycloak 合作
    3. 你行你上,且看文档工程师怎么化腐朽为神奇 -- 记录 ClickHouse 合作
    4. 皆大欢喜,APISIX 登上 OPA 生态的过程 -- 记录 OPA 合作
  5. 在 A+ 轮创业公司碰到的无语事件。

    1. 如何整治双标老板

    2. 如何带领无技术背景的文档同事入门和精通命令行

    3. 不要过度依赖线上预览环境,也许明天预算被砍了,环境就无了

    4. 出尔反尔之说好的远程办公不算数了?

    5. 假公济私之施加压力企图利用公司流程推动社区 PR 合并 but failed

  6. 我报名参加 TCWorld 的议题,综合考虑到上海疫情可能会延期、我的议题不一定会被选上等因素,先做个 trailer 版本看看。

  7. 从零开始建站过程中碰到的问题和解决方法。

  8. 简单聊一聊开源项目文档工程师应该具备的基础和进阶技能吧:文字、翻译、测试思维、思考方式等。

  9. 买一个域名。

  10. 把简历也放上来。

· 8 min read
Yilin Zeng

起因#

文档工程师编辑和润色一篇研发提供的初稿要多久?研发可能不太在意这个问题,只关注最终结果。但是文档组在意这个问题,初稿决定了这篇文章的下限在哪,而我们做的工作是不断优化和雕琢细节,提高它的上限。举个简单的例子,我们把初稿比作原材料,文档工程师比作厨子。如果原材料和厨子之中有一个不够好,那么最终的成品也不会是最接近其上限的。文档工程师在这个过程中扮演的角色至关重要。

研究博客署名的起因来自于一次同事与研发的闲聊,聊到编辑和润色一篇初稿的时间并不比研发自己写初稿的时间短,它也是一件很耗费时间和精力的工作。这个研发老哥很诧异,他说:“那你们也应该共同署名才对,这个必须要有你们的 credit。”

现状是每篇博客都只有一个作者,也就是初稿的提供者。怎么给这些博客和将来的博客添加双作者成了一个需求。

调研过程#

通常都是我们给研发提需求的,现在好了,自己给自己挖了个坑,研发给我们提了个需求。

确认需求是否合理#

首先,得感谢这个研发老哥提出需求,它很合理。付出了时间和精力就应该获得署名,没有文档工程师,这篇博客就不会变得这么好。其次,当时的文档团队内部也有这个需求,大家脸皮都不够厚,没有主动提出来要加名字。最后,双作者可以体现工作量和贡献度,为提名 committer 提供了坚实的基础条件。不然提名的时候老是会被打回来,你就是个写文档的,都是在别人的基础上修改而已,我怎么知道你到底做了什么贡献?怎么量化你的工作呢?双作者就完美解决了这个问题。

调研实现需求的几种方式#

调研的方式很简单,有手有嘴就行。一是 Google 搜索一下它的实现方式,看看官方问答和其他用 Docusarus 的人是怎么弄的,照葫芦画瓢抄一抄就好了。二是问问其他玩 Docusarus 的研发老哥是怎么弄的。一来二去找到了两种实现方式。

第一种是直接使用双作者模板,在每篇博客上面添加双作者和对应的参数信息,例如:

---title: "Apache APISIX 结合 Authing 实现集中式身份认证管理"authors:  - name: "朱欣欣"    title: "Author"    url: "https://github.com/starsz"    image_url: "https://github.com/starsz.png"  - name: "曾奕霖"    title: "Technical Writer"    url: "https://github.com/yzeng25"    image_url: "https://github.com/yzeng25.png"---

第二种是借助 Docusarus 自带的 authors.yml,在文件里面添加作者的详细信息,然后再回到每篇博客添加简单的作者信息,例如:

---title: 浅谈 Docusaurus 博客作者署名的几种方式authors: [yilin, xinxin]---

这种就像是写 method,然后在其他地方 call 这个 method。

结果#

选择了第一种方式的原因是:

  1. 每个文档工程师和作者可能都有多个 title,想用在哪篇博客用哪个 title,自己决定。
  2. 维护 authors.yml 很烦,少维护一个是一个。
  3. 第一种方式门槛低,会读参数英文就知道怎么玩,符合我们团队的使用标准。

然后就是创建和分发模板:

---authors:  - name: "A"    title: "Author"    url: ""    image_url: ""  - name: "B"    title: "Technical Writer"    url: ""    image_url: ""---

最后就是确认时间点和自行认领博客改造了。

  1. 哪个时间点之后的博客优先处理,之前的不处理或者有空再说。
  2. 每篇博客的负责人是谁,自己把名字加上去。

至此,需求实现了,工作完成了,大家的工作量也更加清晰了。

解析#

双作者的适用范围#

它的名字就已经是一个很好的解释了:适用于多个人共同完成的一篇文章。

人数:可以是两个,可以是三个,也可以是四个。是几个就加几个上去嘛。

title:都是自己写上去的,你想写啥写啥。我们这种情况是一个文档工程师+一个研发,双文档工程师也可以,双研发也可以,不必让模板限制了你的想象力。

到底哪种方式最合适#

这个问题没有标准答案,核心还是看你的需求,没有最好的,只有最合适的。我认为在规则内赋予同事一定的自由度是好事,我也懒得维护 authors.yml 这个文件,所以我选择了第一种方式。它的缺点显而易见:每篇都要调整 6-10 行,比第二种工作量稍大。但它的优点也十分明显:没有 authors.yml 意味着少了一个出问题的地方,少了出现 merge conflict 的可能性。结合同事们的 git 技巧(是的,解决 conflict 对他们来说还是个难题)看来,第一种方式更好。

换一个问题,怎么从深圳到北京?打开百度地图,它会告诉你,你可以坐飞机,坐高铁,开车,甚至步行。想要时间最短的话肯定是飞机,想要准点到的话肯定是高铁,那你非要杠,走路行不行,其实也行。最后还是看你想要的是什么。

能不能两个一起用#

可以但没有必要。接着上一个问题说,假如我是要从深圳到北京的话,我为啥要先坐飞机到中间某个地方再转高铁?除非我是有特定的目的,一定要到中间某个地方办个事见个人之类的。不然这么做完全就是在瞎折腾。

参考#

Docusaurus Blog post authors

Docusaurus Global authors

· 10 min read
Yilin Zeng

前情提要#

前几天刷知乎刷到了一个问题:你见过哪些让你目瞪口呆的 bug?我一下子就想到了之前还在 Rancher 的时候,在使用 npx docusaurus-pdf 生成 PDF 文件的过程中碰到的问题。

初识 docusaurus-pdf#

使用 docusaurus-pdf 生成 PDF 文件的原因非常简单,老板是 sales 出身,他希望能提供 PDF 下载这个选项,让有需要的人在内网和离线环境也可以看文档。其次,下载 PDF 要提供一些简单的个人信息,可以用这些信息去找到潜在的付费用户。基于以上这两个原因,我们就有了 PDF 文档这个需求。实现这个需求的方式也十分简单,大致分为以下几步。

  1. 通过 GitHub 完成现网文档更新。
  2. 使用 docusaurus-pdf 命令生成 PDF 文件。
  3. 将新的 PDF 文件上传至 OSS。
  4. 填写信息并下载 PDF。

pdf-regular-process

整个过程其实非常简单,关键就是使用 docusaurus-pdf 命令生成文件这一步。刚开始使用的时候其实我也不太懂这行命令是干啥的,能满足需求,冲就完事了。

它的完整形态是这样的:

npx docusaurus-pdf <initialDocsUrl> [filename]

其中:

  • <initialDocsUrl> 是网页链接,是整个 PDF 的第一页,可以是现网地址 www.xxx.example,也可以是本地环境 localhost:3000
  • [filename] 是生成 PDF 的文件名,文件会保存在当前所处的路径下。

举个例子:

npx docusaurus-pdf https://docs.rancher.cn/docs/rancher2.5/_index/ rancherdocs_2.5

会在我现在的路径下生成一份 rancherdocs_2.5.pdf,包含了 Rancher 2.5 的所有文档内容。

docusaurus-pdf 的工作原理#

docusaurus-pdf 的工作原理可以说是极致的简单粗暴:根据导航栏的排列顺序,自动点击每一个页面下方的“下一页”按键,并生成 PDF,直到最后一页没有“下一页”这个按键为止。你可以把它理解为一个有限的 for loop 循环吧。

docusaurus-pdf 的弊端#

毋庸置疑的是 docusaurus-pdf 为我们提供了相当大程度上的便利,但它也有一些弊端,其中最大的一个弊端是只能通过 <initialDocsUrl> 指定起始页,而没有办法指定终止页。这个问题带来了一些困扰:在我的设想中,既然可以生成一份完整版的 PDF, 那就应该可以更进一步完善,例如根据手册和层级分类,生成完整版的子集,这样用户可以更加方便地各取所需。正是因为无法指定终止页,如果坚持要提供不同的手册,那么就会增加非常大的工作量。说实话,这并不是做不到,而是每个月的下载数量并不足以让我花很多时间去做。假设从无到有提供 PDF 是 80 分的话,那提供分类下载肯定是 100 分,但是为了这额外的 20 分,我的工作量加了不止一个数量级,何况每个版本都要做一次,深思熟虑之后,我们一致决定现在提供一整份就可以了。

pdf-thoughts

触发 docusaurus-pdf 无限循环问题的起因#

起因是我当时想做一些优化,通过百度监控我知道了用户经常访问一些页面,但这些页面由于历史原因,藏在很深的层级目录里面(能改,但会给自己挖深坑,所以我没动它们),很难找到。我就想说,要是大家都访问,那我整理一个新的篇章“热点问题”,放到最显眼的地方好了,这下大家都开心。当时也有些偷懒的心态,既然内容一样,直接到 sidebars.js 里面把链接粘过去就好了啊。就像这样:

module.exports = {    rancher2: {        热点问题: [            "rancher2/trending-topics/_index",            "rancher2/.../certificate-rotation/_index",            "rancher2/.../cleaning-cluster-nodes/_index",            "rancher2/.../deployment/_index",            "rancher2/.../install-rancher-on-k8s/_index",            "rancher2/.../requirements/_index",            "rancher2/.../quickstart-manual-setup/_index",            "rancher2/.../cli/_index",            "rancher2/.../single-node-docker/_index",        ],        ...    }}        

本地和线上测试都没有问题,就直接合入主干上线了。然后在更新 PDF 的时候就 gg 了。跟往常一样,输入命令之后,我就下楼抽烟去了。因为这个命令通常需要跑 20~30 分钟,因为生成的文件很大。回来我一看,花了十五分钟,还在跑,嗯非常合理,我先干点别的事情。结果又过了半小时,它还没跑完。再过了一个小时,它还在跑,有限循环变无限循环了,肯定出问题了。这个时候我就有点慌,先把这个修改 revert 掉。然后再回来搞搞 debug。

问题排查过程#

排查的思路非常简单:既然刚开始没问题,那么问题一定出在新增的修改上面。到底是什么原因造成的?

whole-picture

那么新增的修改,到底改了哪些东西呢?

modifications

可以看到主要分为两大块:sidebars.js 和 热点问题的索引页 trending-topics/_index.md。这个时候再排列组合测试一下。

定位问题#

测试案例 1:原先的 + 热点问题的索引页 trending-topics/_index.md,没有问题。

case 1

测试案例 2:原先的 + sidebars.js,出问题了。

case 2

测试之后确定问题出在 sidebars.js 里面,而我改动的内容就是这几行:

module.exports = {    rancher2: {        热点问题: [            "rancher2/trending-topics/_index",            "rancher2/.../certificate-rotation/_index",            "rancher2/.../cleaning-cluster-nodes/_index",            "rancher2/.../deployment/_index",            "rancher2/.../install-rancher-on-k8s/_index",            "rancher2/.../requirements/_index",            "rancher2/.../quickstart-manual-setup/_index",            "rancher2/.../cli/_index",            "rancher2/.../single-node-docker/_index",        ],        ...    }}        

可以把 "rancher2/trending-topics/_index", 排除掉,因为它不会造成任何影响。 那么现在问题就缩小到剩下的 8 行了。

module.exports = {    rancher2: {        热点问题: [            "rancher2/trending-topics/_index",            //问题应该在下面几行            "rancher2/.../certificate-rotation/_index",            "rancher2/.../cleaning-cluster-nodes/_index",            "rancher2/.../deployment/_index",            "rancher2/.../install-rancher-on-k8s/_index",            "rancher2/.../requirements/_index",            "rancher2/.../quickstart-manual-setup/_index",            "rancher2/.../cli/_index",            "rancher2/.../single-node-docker/_index",            //问题应该在上面几行        ],        ...    }}        

这个时候我想起来了 docusaurus-pdf 的工作原理:根据导航栏的排列顺序,自动点击每一个页面下方的“下一页”按键,并生成 PDF,直到最后一页没有“下一页”这个按键为止。也去 npmjs.com 看了官方的定义和使用案例。

definition

图里说了,找不到下页就停下来了。那换个角度想想:是不是因为一直都能找到下一页,所以就停不下来?

behaviors

在仔细观察 sidebars.js 里面的修改之后,我发现确实是的,直接引用已有的页面确实会造成无限循环的问题,有些页面的下一页并不是我们想要看到的,图里面的下一个 trending topic。

解决问题#

解决的方法也很简单:创建新页面,归到 trending-topics 下面,放一样内容就好了。

module.exports = {    rancher2: {        热点问题: [            "rancher2/trending-topics/_index",            "rancher2/trending-topics/certificate-rotation/_index",            "rancher2/trending-topics/cleaning-cluster-nodes/_index",            "rancher2/trending-topics/deployment/_index",            "rancher2/trending-topics/install-rancher-on-k8s/_index",            "rancher2/trending-topics/requirements/_index",            "rancher2/trending-topics/quickstart-manual-setup/_index",            "rancher2/trending-topics/cli/_index",            "rancher2/trending-topics/single-node-docker/_index",        ],        ...    }}        

替换完之后再测试,运行 docusaurus-pdf 命令,半个小时完事,成功生成文件,并且内容符合预期。

后续思考#

触发这个问题的先决条件其实挺苛刻的:

  1. 使用 Docusaurus 建站。
  2. 使用 docusaurus-pdf 生成 PDF。(大多数人用不到这个命令)
  3. sidebars.js 存在造成无限循环的内容。(大多数人会按常理出牌,不会触发这个问题)

一开始我是觉得这个锅应该甩给 Docusaurus,按正常逻辑来讲,sidebars.js 就不应该允许出现重复的页面。一旦出现了重复页面,应该在构建的时候就直接报错提示才对。但仔细想想,这一波我也没按常理出牌,恰巧碰到了一些问题而已,不能全怪它。

另一个细思恐极的点是,sidebars.js 既支持手打全量链接,又支持批量指定某个文件夹底下的全部链接。幸好当时选的前者,很笨但很管用。如果使用了后者,这个 debug 过程怕是更加扑朔迷离。

参考#

最后,再贴两个 pr 链接,证明我真的做过这个事情。

PR 597

PR 600