使用 pagefind 添加博客搜索功能

这周用 pagefind 给博客添加一个 搜索页面,如果你感兴趣可以搜索看看 (ノ>ω<)ノ

一直都想给博客添加一个搜索功能,加上最近开始写周刊,里面整理了不少的链接,有时候我想找点东西,能够搜索的话就会方便很多。

以前尝试过 algolia ,但配置起来有点麻烦,也显得很重,效果并不满意。

这周看到了一个开源项目 pagefind,它可以对构建好的 HTML 进行索引和搜索,配置简单,开箱即用,没有额外的第三方服务,很符合我的需要。

关于 pagefind

Pagefind 是一个完全静态的搜索库,其目标是在大型网站上运行良好,同时尽可能少地占用用户带宽,并且无需托管任何基础设施。

Pagefind 的目标是,拥有数万个页面的网站应能让用户在浏览器中进行搜索,同时尽可能减少带宽消耗。

Pagefind 的搜索索引被分割成若干块,因此在浏览器中进行搜索只需加载搜索索引的一小部分。

Pagefind 可以在一个 10,000 页的网站上运行全文搜索,包括 Pagefind 库本身在内的总网络有效载荷不到 300kB。 对于大多数网站来说,这将接近 100kB。

pagefind

pagefind 的一些特点:

  • 零配置支持多语言网站
  • 使用 NodeJS 索引库索引 任何内容(例如 PDF、JSON 文件或字幕)
  • 以相同的低带宽占用提供所有功能

对我来说,它最大的优点就是配置简单,不依赖第三方服务,而且搜索效果也不错。

Weekly#11 中分享过一篇文章,里面的观点我觉得说的很对:

入门(Getting Started)不应该是在构建产品之后才考虑的问题。入门就是产品!

我认为这值得重构你的整个产品,以便实现快速入门。去掉强制配置。让设置 API 令牌变得极其简单。消除所有障碍。让用户能够在几分钟内在他们的笔记本电脑上使用你的产品。

你可能会说,我不知道,"谁在乎懒惰的用户"。那就让我靠在豆袋椅上,打开一袋多力多滋,解释一下吧:

目前有 7,000,000,000 种开发工具。用户没有那么多精力和耐心去深入了解你的 LRU 缓存 NPM 包或其他东西有什么不同。抱歉了!

It's hard to write code for computers, but it's even harder to write code for humans!

配置 pagefind

配置 pagefind 很简单,你只需要两步:

  1. 执行 npx -y pagefind --site publish 生成索引,其中 publish 是你的静态页面存放的目录。
  2. 引用对应的 CSS,JS,并且添加一个 DOM 元素让 pagefind 挂载
<link href="/pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-ui.js"></script>
<div id="search"></div>
<script>
  window.addEventListener('DOMContentLoaded', (event) => {
  new PagefindUI({ element: "#search", showSubResults: true });
  });
</script>

这样你就拥有搜索功能了 ヾ(´∀ ˋ)ノ

下面分享一下我是如何集成的。

CI/CD 中添加索引指令

我的博客1是部署在 Netlify,我只需要在构建的最后,添加一行执行索引的指令就完成索引了。

#!/bin/bash

# Enable command printing (debug mode)
set -x

# Only build when `publish` change
git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF publish

# index.xml is for https://www.v2ex.com/xna
cp -f publish/rss.xml publish/index.xml

+ # see: https://pagefind.app/docs/multilingual/#opting-out-of-multilingual-search
+ npx -y pagefind --site publish --force-language zh-CN

# Disable debug mode
set +x

如果你仔细看的话,会发现我的指令添加了 --force-language zh-CN 的 option,这会告诉 pagefind 要将不同语言的页面都生成到同一个索引里。

pagefind 的默认逻辑是按照语言各自建立索引,当你的页面的 lang 是 en 的时候,它只会检索 en 页面对应的索引,而不会检索 zh-CN 页面的索引。

但是我希望在一个统一的地方,能够搜索到我博客所有的内容,因此我需要它将不同语言的页面索引放到一起。

引用 findpage 资源

相比于在文章页面上添加搜索,我更倾向于一个独立的搜索页面,避免搜索结果影响文章页面的布局。

单独一个页面,在我不需要的时候也可以轻易移除。

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Search</title>
    <meta name="author" content="Spike Leung" />
    <meta name="description" content="&quot;&quot;" />
    <meta name="generator" content="Org Mode" />
    <link rel="stylesheet" href="../styles/style.css" type="text/css"/>
    <link rel="icon" href="/favicon.ico" type="image/x-icon">
    <link href="/pagefind/pagefind-ui.css" rel="stylesheet">
    <script src="/pagefind/pagefind-ui.js"></script>
  </head>
  <body>
    <div id="search"></div>
    <script>
      window.addEventListener('DOMContentLoaded', (event) => {
      new PagefindUI({ element: "#search", showSubResults: true, showImages: false });
      });
    </script>
  </body>
</html>

页面上我设置了 lang="zh-CN" ,findpage 会基于 lang 去匹配索引和组件的多语言文字。

之前我的页面都是 lang="en" ,pagefind 将页面按照 en 索引,导致我搜索不到任何内容。

因此我也更新了博客页面的 lang 属性,从 en 改为了 zh-CN,这样对于使用屏幕阅读器的人也会友好一点

另外我将 showIamges 设置成了 false,因为我的博客文章基本没有封面图,图片还会增加搜索时的带宽消耗。

写在最后

如果你还有更好的搜索服务,欢迎分享 (゚∀。)

感谢 pagefind 提供这样简单好用的搜索服务!\m/ >_< \m/

如果你也有搜索静态页面的需要,试试看吧!

Footnotes:

1

如果你对我的博客是如何搭建感兴趣,可以看 使用 org-publish 发布博客 (≖ᴗ≖๑)

Author: Spike Leung

Date: 2024-11-16 Sat 00:00

License: CC BY-NC 4.0