JavaScript API

Pagefind 的搜索能力可以直接通过浏览器 JavaScript 调用。这样可以保留自己的搜索弹窗、输入框、结果列表和交互逻辑。

动态导入

Pagefind 生成索引后,会在输出目录中提供搜索入口脚本。本项目把搜索资产输出到 /_pagefind/

js
const pagefind = await import("/_pagefind/pagefind.js");

可以手动初始化,也可以等第一次搜索时自动初始化:

js
await pagefind.init();

执行搜索

js
const pagefind = await import("/_pagefind/pagefind.js");
const search = await pagefind.search("静态搜索");

搜索结果对象里的 results 默认只包含轻量信息。真正的标题、URL、摘要和元数据需要按需加载:

js
const rows = await Promise.all(
  search.results.slice(0, 8).map((result) => result.data())
);

结果数据通常包含:

字段 说明
url 结果页面 URL
excerpt 带高亮标记的摘要
plain_excerpt 不带高亮 HTML 的纯文本摘要
meta.title 页面标题
meta.image 页面图片元数据
sub_results 页面内更具体的命中片段

一个最小搜索框

html
<input id="search" type="search" placeholder="搜索文档">
<div id="results"></div>

<script type="module">
  const input = document.querySelector("#search");
  const results = document.querySelector("#results");
  let pagefindPromise;

  function loadPagefind() {
    pagefindPromise ||= import("/_pagefind/pagefind.js");
    return pagefindPromise;
  }

  input.addEventListener("input", async () => {
    const query = input.value.trim();
    if (!query) {
      results.innerHTML = "";
      return;
    }

    const pagefind = await loadPagefind();
    const search = await pagefind.search(query);
    const rows = await Promise.all(search.results.slice(0, 5).map((item) => item.data()));

    results.innerHTML = rows
      .map((row) => `<a href="${row.url}"><strong>${row.meta.title}</strong><p>${row.excerpt}</p></a>`)
      .join("");
  });
</script>

excerpt 已经适合放入结果摘要,但其他原始字段如果来自不可信内容,仍应在模板层做转义。

输入防抖

搜索框通常会随着用户输入不断触发查询。可以自己写防抖,也可以使用 pagefind.debouncedSearch()。如果用户很快输入了新内容,较旧的防抖搜索可能返回 null,渲染前需要判断。