为 Docusaurus 添加 Algolia 搜索功能
本文介绍使用 Algolia 为 Docusaurus 网站添加搜索功能。
配置 Algolia 教程 🔎
我参考了这篇文章为我的网站添加了搜索功能。但是在实践过程中遇到了一些问题,原文章说明也不够详细,因此决定写一篇更加详细的博客来记录整个配置过程。
获取 Algolia API
本小节的目标是获取 Algolia 的这三个 API:
1. Application ID
2. Search API Key
3. Admin API Key
API 名称对应关系
Algolia中 的 API 名称和代码中的名称并不完全一致,对应关系如下:
Application ID -> appId
Search API Key -> apiKey
Application ID -> ALGOLIA_APP_ID
Admin API Key -> ALGOLIA_API_KEY
注册 Algolia 账户
- 打开 Algolia官网 ,使用Github账号注册并登录
- 点击
Not now ...跳过初始设置
获取 API
- 打开
Settings配置页面
- 查看API Key
上面三个 API 即为所需,此页面可保持打开,方便后续复制粘贴。 至此,三个 API 应已成功获取。
不要分享 Admin API Key! 这是敏感信息,泄露可能导致安全问题。!
只找到两个 API ?
如果在查看 API 的时候看到只有两个 API,分别是 Application ID 和 Search API Key,没有 Admin API Key ?!那说明刚才没有严格按照这个步骤走,现在看到的是Algolia 默认创建的 Application Docsearch 。该 Application 暂时是没有 Admin API Key 密钥的。(按官方的教程一步步走应该会有,但我没试过。🥱)解决方法是再创建一个 Application,在这里:Settings/API Keys
填上名称后,其他配置保持默认,直接点击 Next:Review & Confirm -> Create Application。新Application 的 API 获取方式与上面一样。
创建 Actions Secrets
- 打开存放网站项目代码的 Github 仓库,进入:
Settings/Secrets and variables/Actions。
- 返回 Algolia 页面,复制
Application ID:
- 返回 Github 页面,填上名称
ALGOLIA_APP_ID,粘贴秘钥,点击Add secret。
- 返回 Algolia 页面,复制
Admin API Key:
- 返回 Github 页面,填上名称
ALGOLIA_API_KEY,粘贴秘钥,点击Add secret。
- 预期结果:
创建 Github Actions workflow
- 可以在本地项目根目录下创建
.github/workflows/docsearch.yml文件:
以下将提供两个 docsearch.yml 配置,分别为原始版本和改进版本。
这是两个版本的对比:
原始版本:从参考资料的文章中复制修改,功能基础。
改进版本:解决实际问题而生——网站有100+记录但只爬取到16条且显示成功。
改进版本新增功能:
- 输出详细错误信息
- 爬取记录过少时工作流失败并提示
配置要点:根据网站实际记录数调整高亮行配置,如网站约100条则配置为100,后续可随内容变化调整。如不知道自己的网站记录具体有多少条,可以先值改低一点,比如改为1,这样即使只爬取到一条记录,也会显示执行成功,这时候已经得到具体的记录数了,再修改为具体记录数相近的数值。
- 改进
- 原始
name: DocSearch Scraper
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
algolia:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install jq
run: sudo apt-get install jq
- name: Validate docsearch.json exists
run: |
if [ ! -f "docsearch.json" ]; then
echo "docsearch.json not found!"
exit 1
fi
- name: Get the content of docsearch.json as config
id: algolia_config
run: echo "config=$(cat docsearch.json | jq -r tostring)" >> $GITHUB_OUTPUT
- name: Run algolia/docsearch-scraper image
env:
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }}
CONFIG: ${{ steps.algolia_config.outputs.config }}
run: |
echo "Starting DocSearch scraper..."
# 捕获输出并检查退出码
docker run \
--env APPLICATION_ID=${ALGOLIA_APP_ID} \
--env API_KEY=${ALGOLIA_API_KEY} \
--env "CONFIG=${CONFIG}" \
algolia/docsearch-scraper > scraper_output.log 2>&1
echo "DocSearch scraper execution finished."
- name: Validate scraping results
run: |
# 显示完整的抓取日志(便于调试)
echo "=== SCRAPER OUTPUT ==="
cat scraper_output.log
echo "=== END OUTPUT ==="
# 检查是否有错误信息
if grep -q "ERROR\|Exception\|Traceback" scraper_output.log; then
echo "ERROR: Scraper encountered errors during execution"
exit 1
fi
# 提取抓取的记录数
hits=$(grep "Nb hits:" scraper_output.log | awk '{print $3}')
if [ -z "$hits" ]; then
echo "ERROR: Could not determine number of hits"
exit 1
fi
echo "Records scraped: $hits"
# 验证记录数量是否合理
if [ "$hits" -lt 100 ]; then
echo "ERROR: Insufficient records scraped ($hits < 100). This indicates incomplete scraping."
exit 1
fi
echo "SUCCESS: Adequate records scraped ($hits >= 100)"
- name: Archive scraper logs
uses: actions/upload-artifact@v4
if: always()
with:
name: scraper-logs-${{ github.run_id }}-${{ github.run_attempt }}
path: scraper_output.log
name: DocSearch Scraper
# 定义工作流触发条件
on:
# 允许手动触发工作流
workflow_dispatch:
# 自动运行 (UTC时间)
schedule:
- cron: '0 0 * * *'
# 定义工作流任务
jobs:
algolia:
# 运行环境
runs-on: ubuntu-latest
steps:
# 检出代码仓库
- uses: actions/checkout@v3
# 安装 jq 工具用于处理 JSON
- name: Install jq
run: sudo apt-get install jq
# 验证配置文件是否存在
- name: Validate docsearch.json exists
run: |
if [ ! -f "docsearch.json" ]; then
echo "docsearch.json not found!"
exit 1
fi
# 读取并设置 Algolia 配置
- name: Get the content of docsearch.json as config
id: algolia_config
run: echo "config=$(cat docsearch.json | jq -r tostring)" >> $GITHUB_OUTPUT
# 运行 DocSearch 爬虫
- name: Run algolia/docsearch-scraper image
env:
# 从 secrets 获取 Algolia 凭据
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }}
CONFIG: ${{ steps.algolia_config.outputs.config }}
run: |
echo "Starting DocSearch scraper..."
docker run \
--env APPLICATION_ID=${ALGOLIA_APP_ID} \
--env API_KEY=${ALGOLIA_API_KEY} \
--env "CONFIG=${CONFIG}" \
algolia/docsearch-scraper
echo "DocSearch scraper completed successfully."
两个版本的详细比对
功能完整性对比
1. 错误检测和验证机制
原始版本(较差):
run: |
echo "Starting DocSearch scraper..."
docker run \
--env APPLICATION_ID=${ALGOLIA_APP_ID} \
--env API_KEY=${ALGOLIA_API_KEY} \
--env "CONFIG=${CONFIG}" \
algolia/docsearch-scraper
echo "DocSearch scraper completed successfully." # 总是显示成功
改进版本(较好):
- name: Validate scraping results
run: |
# 完整的验证机制
# 1. 显示完整日志
cat scraper_output.log
# 2. 错误检测
if grep -q "ERROR|Exception|Traceback" scraper_output.log; then
echo "ERROR: Scraper encountered errors"
exit 1
fi
# 3. 结果数量验证
if [ "$hits" -lt 100 ]; then
echo "ERROR: Insufficient records"
exit 1
fi
2. 日志记录和调试能力
原始版本缺陷:
- 没有捕获详细输出
- 遇到问题时难以诊断
- 无法查看实际执行过程
改进版本优势:
# 捕获完整输出用于分析
docker run ... > scraper_output.log 2>&1
# 显示完整日志便于调试
echo "=== SCRAPER OUTPUT ==="
cat scraper_output.log
具体改进点分析
1. 真实成功验证
原始版本问题:
❌ 只要程序运行完成就显示成功
❌ 无法区分"运行完成"和"成功完成"
❌ 16条记录也会显示成功
改进版本优势:
✅ 检查实际抓取的记录数量
✅ 验证是否达到预期标准
✅ 只有真正成功才标记为成功
2. 错误处理机制
原始版本问题:
❌ 没有错误检测
❌ 静默失败无法发现
❌ 网络问题或配置错误无法识别
改进版本优势:
✅ 自动检测错误信息
✅ 关键词匹配发现异常
✅ 及时终止并报告错误
3. 调试和监控能力
原始版本限制:
❌ 无日志记录
❌ 无法回溯问题
❌ 难以优化性能
改进版本功能:
✅ 完整日志捕获
✅ 日志归档保存
✅ 便于问题分析和性能优化
实际场景对比
场景1:网络连接问题
原始版本结果:
- 只抓取了16条记录
- 工作流显示"成功"
- 你不知道有问题
改进版本结果:
- 只抓取了16条记录
- hits < 100,工作流失败
- 通过日志可以发现问题原因
场景2:配置文件错误
原始版本结果:
- 程序异常退出但仍可能显示成功
- 无法定位配置问题
改进版本结果:
- 捕获错误日志
- grep 检测到 "ERROR" 关键词
- 工作流正确失败并提示错误
场景3:正常运行
原始版本:
- 显示成功但信息有限
改进版本:
- 显示详细的执行过程
- 验证记录数量充足
- 保存完整日志供后续分析
可靠性和维护性
1. 监控能力
原始版本:
- 盲目信任执行结果
- 无法主动发现问题
改进版本:
- 主动验证执行质量
- 设置合理的阈值标准
- 及早发现潜在问题
2. 故障排查
原始版本:
- 出问题时需要手动检查
- 缺乏诊断信息
改进版本:
- 自动化的错误检测
- 完整的日志记录
- 快速定位问题根源
3. 持续改进
原始版本:
- 难以收集运行数据
- 无法优化性能
改进版本:
- 积累历史执行日志
- 分析性能趋势
- 持续优化工作流
总结
改进后的版本在以下方面明显优于原始版本:
- 准确性:从表面成功到真实成功验证
- 可靠性:完善的错误检测和处理机制
- 可维护性:详细的日志记录和分析能力
- 监控性:主动的健康检查和预警机制
- 透明度:完整的执行过程可视化
如果想配置成部署完成后便触发该工作流,可以参考这篇文章。但我觉得手动和定时触发已经完全足够,因此没有尝试其他触发方式。
创建 docsearch.json
下面黄色高亮部分需要改成自己的配置,index_name可自定义,但要和后续的docusaurus.config.js配置一致,start_urls和sitemap_urls改成自己的链接。
{
"index_name": "test-site",
"start_urls": ["https://eureka12138github.github.io/"],
"sitemap_urls": ["https://eureka12138github.github.io/sitemap.xml"],
"js_render": true,
"js_wait": 1,
"selectors": {
"lvl0": {
"selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",
"type": "xpath",
"global": true,
"default_value": "Documentation"
},
"lvl1": "header h1, article h1",
"lvl2": "article h2",
"lvl3": "article h3",
"lvl4": "article h4",
"lvl5": "article h5, article td:first-child",
"lvl6": "article h6",
"text": "article p, article li, article td:last-child"
},
"custom_settings": {
"attributesForFaceting": ["type", "lang", "language", "version", "docusaurus_tag"],
"attributesToRetrieve": ["hierarchy", "content", "anchor", "url", "url_without_anchor", "type"],
"attributesToHighlight": ["hierarchy", "content"],
"attributesToSnippet": ["content:10"],
"camelCaseAttributes": ["hierarchy", "content"],
"searchableAttributes": [
"unordered(hierarchy.lvl0)",
"unordered(hierarchy.lvl1)",
"unordered(hierarchy.lvl2)",
"unordered(hierarchy.lvl3)",
"unordered(hierarchy.lvl4)",
"unordered(hierarchy.lvl5)",
"unordered(hierarchy.lvl6)",
"content"
],
"distinct": true,
"attributeForDistinct": "url",
"customRanking": ["desc(weight.pageRank)", "desc(weight.level)", "asc(weight.position)"],
"ranking": ["words", "filters", "typo", "attribute", "proximity", "exact", "custom"],
"highlightPreTag": "<span class='algolia-docsearch-suggestion--highlight'>",
"highlightPostTag": "</span>",
"minWordSizefor1Typo": 3,
"minWordSizefor2Typos": 7,
"allowTyposOnNumericTokens": false,
"minProximity": 1,
"ignorePlurals": true,
"advancedSyntax": true,
"attributeCriteriaComputedByMinProximity": true,
"removeWordsIfNoResults": "allOptional",
"separatorsToIndex": "_",
"synonyms": [
["js", "javascript"],
["ts", "typescript"]
]
}
}
注意:绿色标注的两行配置(
js_render和js_wait)非常重要。没有这两句的话,Algolia可能只能爬取到网站首页的数据。在除首页外的页面点击F12,可能会发现404页面,但此时网页是可以正常显示的。这种显示和源码不一致的情况导致无法爬取到完整数据。加上这两句表示渲染完成后再爬取,如此便能正常获取所有数据。
如果后续增加
i18n国际化配置,想要爬取多语言数据,则需要修改docsearch.json中的sitemap_urls。以英文站为例:
"sitemap_urls": [
"https://eureka12138github.github.io/sitemap.xml",
"https://eureka12138github.github.io/en/sitemap.xml"
],
配置 docusaurus.config.js
- 位置示意:
- 新增代码:
//添加Algolia搜索
algolia: {
// Application ID
appId: '********',
// Search API Key
apiKey: '*******************',
indexName: 'test-site',//与docsearch.json中的index_name一致
searchPagePath: 'search',
contextualSearch: true
},
网站部署
将代码 git push 到远端仓库中。
手动触发工作流爬取信息
在GitHub对应仓库中,点击 Actions,选择Docsearch scraper,点击Run workflow,即可触发该工作流,爬取网站信息并生成索引文件用于后续Algolia搜索。
运行完毕:
查看 Algolia 记录
- 点击
Data Source
- 点击
indices,从下图可知索引文件已经生成,在索引test-site下一共找到了134个记录。这个记录数量取决于网站内容,如果内容多,记录也多。我这个只是演示网站,只有134记录,正常的索引记录可能会有几千甚至上万个。
注意,只有这里出现了和你网站内容所匹配的记录时,才表示配置成功。如果网站内容很多,结果这里的记录只有寥寥几条,那明显是某个地方出错了。可能是这里的两行没有加?
将网站部署到GitPages
其实在本地就可以查看结果了,部署再看是为了进一步确认结果是否正确。毕竟有的时候本地运行的好好的,但是部署到GitPages的时候,就出现了问题。(说的就是你!i18n,坑爹的现在闪烁问题还没能解决。。。😑)
部署完成:
结果
大功告成!现在网站可以使用搜索功能了!🎉
这个过程还挺曲折的,多亏了下面的参考资料,没有他的文章参考,我怕是难以完成这个搜索功能。但即使有参考,也并非一蹴而就的,为了实现这个搜索功能,我花了很多时间,也走了很多弯路,希望这个总结能帮助到有缘之人。(也可能是未来的自己?🥱)
📚 参考资料
[1]. AlanWang's Blog
