笔记

静态站点的搜索实现方案对比

比较 Pagefind、Algolia DocSearch、FlexSearch 等静态站点搜索方案的适用场景和权衡。

静态站点没有服务器端运行时,搜索功能的实现方式与动态站点有本质区别。核心问题是:索引在哪里生成,查询在哪里执行。

方案分类

构建时索引 + 客户端查询

代表方案:Pagefind、FlexSearch、MiniSearch

  • 原理:构建时生成搜索索引(通常是 JSON 文件),客户端加载索引后执行查询。
  • 优点:完全静态,无需外部服务,隐私友好。
  • 缺点:索引文件随内容量增长而增大,首次加载可能较慢。
  • 适用场景:内容量中等(几百到几千篇)、对隐私敏感、不想依赖外部服务。

外部服务索引 + API 查询

代表方案:Algolia DocSearch、MeiliSearch

  • 原理:内容同步到外部服务,客户端通过 API 查询。
  • 优点:搜索质量高,支持模糊匹配、同义词、权重等高级功能。
  • 缺点:依赖外部服务,有成本(免费额度有限),隐私问题(内容发送到第三方)。
  • 适用场景:内容量大、对搜索质量要求高、有预算。

服务端查询

代表方案:自建 Elasticsearch、SQLite FTS

  • 原理:服务器端维护索引,客户端发送查询请求。
  • 优点:完全控制,可定制性最高。
  • 缺点:需要维护服务器,增加复杂性。
  • 适用场景:有运维能力、对隐私和性能有极端要求。

本博客的选择

本博客选择 Pagefind,原因:

  1. 完全静态:索引在构建时生成,查询在客户端执行,无需外部服务。
  2. 隐私友好:搜索数据不离开用户浏览器。
  3. 轻量:索引文件经过压缩,对构建产物大小的影响可控。
  4. 易集成:与 Astro 的构建流程自然衔接。

Pagefind 的局限是搜索质量不如 Algolia 等商业服务,但对于个人博客的内容量来说完全够用。

集成要点

# 构建后生成索引
npx pagefind --site dist

在客户端加载 Pagefind:

window.addEventListener('DOMContentLoaded', async () => {
  const pagefind = await import('/pagefind/pagefind.js');
  await pagefind.init();
  const search = await pagefind.search('关键词');
  // 处理结果
});

权衡总结

方案 隐私 搜索质量 维护成本 适用内容量
Pagefind 高 中 低 中小
Algolia 低 高 中 大
自建服务 高 高 高 不限

本笔记的状态

这是一个 growing 状态的笔记。目前只覆盖了基本的方案对比,后续会补充实际集成中的性能测试数据和具体的配置细节。

评论