Pagefind 是专为静态网站设计的客户端搜索库。它可以为使用静态网站生成器(SSG)创建的网站或使用 Next.js、Gatsby、Hugo、Jekyll 等框架构建的网站添加强大的搜索功能。它可以在本地安装和配置,无需任何外部 API 或服务密钥,因此启动和运行起来非常简单快捷。
工作原理
Pagefind 的工作流程如下
- 索引阶段:网站建成后,它会分析 HTML 文件以创建搜索索引。在这一阶段,将提取并处理文本内容、标题、元数据等,并创建一个 JS 文件,使索引数据可用。这意味着只有在构建时生成 HTML 才能使用它。
- 搜索 API:创建索引后,您可以使用提供的 JavaScript API 在网站上实现搜索界面。
- 创建用户界面:当用户输入搜索查询时,Pagefind 会使用预先创建的索引快速查找相关页面和部分以提供搜索结果,我们只需使用这些结果来实现用户界面即可。
你可以在文档中了解更多关于这些功能和使用方法的信息。
Pagefind 入门 | Pagefind - 大规模静态低带宽搜索
快速入门!
编写脚本
让我们开门见山地开始吧!你不需要安装任何软件包,只需按照以下步骤操作即可。开发环境使用的是Next.js 15 和
pnpm
。
首先,在 package.json 中
添加postbuild
"脚本":{ { ...
// ...
"postbuild":"npx pagefind --site .next --output-path public/pagefind"、
// ...
},
**请注意,为了被索引,需要生成 HTML,而为了生成 HTML,需要构建 NEXT。**添加此脚本并运行编译后,您应该可以在 public 文件夹下看到与 pagefind 相关的文件。
现在,我们只需导入并使用在此创建的pagefind.js
。
API 调用
首先,完整的代码如下所示
导出默认函数 Search() {
const [search, setSearch] = useState("");
const [results, setResults] = useState<PagefindResult[]>([]);
const [pagefind, setPagefind] = useState<any>(null);
useEffect(() => {
const initPagefind = async () => {
try {
// 尝试在运行时动态加载
setPagefind(
await import(
// @ts-expect-error
"./pagefind/pagefind.js"。
),
);
} catch (error) {
console.error("Pagefind 初始化失败:", error);
}
};
// 仅在客户端执行
if (typeof window !== "undefined") {
initPagefind();
}
}, []);
const handleSearch = async (e: any) => {
setSearch(e.target.value);
if (!pagefind || e.target.value === "") {
setResults([]);
返回;
}
} const search = await pagefind.search(e.target.value);
const results = await Promise.all(search.results.map((r) => r.data()));
console.log(results);
setResults(results);
};
返回 (
<div
<input
type="text"
value={search}
onChange={handleSearch}
placeholder="请输入您的搜索词..."
/>.
<div
{results.map((result, i) => (
<div key={result.url}>
<a href={result.url}>{result.meta.title}</a>。
</div
))}
</div> </div
</div
);
}
创建用户界面
现在我们已经完成了调用,让我们来看看结果。
您需要查看的主要内容有
- excerpt:这是内容中关键词的部分解析。
- **meta:**获取内容中的元信息,对于标题,这是遇到的第一个
h1
标签;对于图片,这是h1
标签之后遇到的第一个图片
标签。
所有这些都可以通过其他选项进行自定义,请查看文档!
问题
我的博客有四种语言(韩语、英语、中文和日语),搜索显示的是所有语言的文章。
对于多语言页面来说,这种情况并不少见,因此 pagefind 当然提供了多语言搜索功能。不过,它是通过html
标签的lang
属性值来判断的。
但在 Next.js,你必须在 Layout 中设置该属性,而且据我所知,在创建静态页面时没有办法获取 lang 值...(如果有,请告诉我)
变通方法
于是我采取了一种变通方法,使用 pagefind 中的过滤器功能。我在每个页面的h1
标签中添加了以下附加属性
<h1
data-pagefind-filter="lang[data-lang]"
data-lang={params.lang}
className="text-3xl md:text-5xl font-bold"
>>
{标题}
</h1>
当我们进行 API 请求时,我们可以添加过滤器
const search = await pagefind.search(e.target.value, {
filters: {
lang:"en"、
},
});
结论
我们已经了解了如何使用小型轻量级库 pagefind 快速实现搜索功能。在不依赖外部服务的情况下创建自己的搜索索引,不仅可以保护隐私和进行控制,还能提供快速响应的用户体验,这对运行博客或文档网站非常有用。