跳到正文
技术

用 Pagefind 给静态博客加全文搜索

📅 创建 ·☕ 约 1 分钟·✍ 335 字
用 Pagefind 给静态博客加全文搜索

为什么不用客户端搜索库

一开始我想过把文章标题和摘要塞进一个 JSON,前端自己过滤。问题是:

  • 文章一多,那个 JSON 就有几百 KB,首屏白等;
  • 只能搜标题和摘要,搜不到正文;
  • 中文分词要自己搞。

Pagefind 怎么做的

它在构建之后扫描 dist/ 里的 HTML,生成一堆分片索引文件:

npm run build   # astro build && pagefind --site dist

产物长这样:

dist/pagefind/
├─ pagefind.js          # 运行时模块
├─ pagefind-entry.json  # 索引清单
└─ fragment/*.pf        # 分片索引

浏览器只在需要时下载命中的那几个分片,不是整个索引。

关键:别让它进首屏

我把搜索做成了「懒到骨子里」:

input.addEventListener('focus', function () { load(); });

用户点进输入框的那一刻,才开始 import('/pagefind/pagefind.js')。 在那之前,首屏 JS 里跟搜索有关的字节数是 0

自己渲染结果

Pagefind 自带的 UI 组件有几十 KB,而且样式不好覆盖。它的 JS API 其实很短:

const pf = await import('/pagefind/pagefind.js');
await pf.options({ excerptLength: 26 });
const search = await pf.search('芙宁娜');
const results = await Promise.all(
  search.results.slice(0, 8).map((r) => r.data())
);
// results[i] → { url, excerpt, meta: { title, date } }

excerpt 里已经带好了 <mark> 高亮标签,直接插进 DOM 就行。

踩到的坑

  1. 本地开发搜不到东西 —— Pagefind 只认构建产物,astro dev 下没有索引。要先 npm run build
  2. 动态 import 会被打包器处理 —— 用 is:inline 的内联脚本,路径原样保留。
  3. 高亮颜色 —— <mark> 默认是刺眼的黄色,记得用主题变量接管。

结论:静态站做搜索,Pagefind 基本是目前的最优解。

更多「技术」