[Pagefind] Astroの静的サイトに全文検索を後付けする

Tech
[Pagefind] Astroの静的サイトに全文検索を後付けする

WordPress には検索機能が標準で付いていますが、Astro の静的サイトには当然ありません。 そこで Pagefind を使って全文検索を後付けしました。サーバー不要・ビルド時にインデックスを作る方式で、静的サイトと相性抜群です。

Pagefind とは

  • ビルド済みの HTML を読み込んでインデックスを作る静的検索ライブラリ
  • 実行にサーバーや API は不要。インデックスとJS/CSSを配信するだけ
  • 検索UI(pagefind-ui)も同梱されている

つまり「サイトをビルド → 出来上がった dist/ を Pagefind に食わせる」だけで検索が付きます。

インストールとビルド設定

npm i -D pagefind

ポイントは、Astro のビルドが終わった後に Pagefind を走らせること。package.json の build スクリプトを繋げておきます。

{
  "scripts": {
    "build": "astro build && pagefind --site dist"
  }
}

pagefind --site distdist/ を走査して、dist/pagefind/ にインデックスと UI 一式(pagefind-ui.js / pagefind-ui.css など)を生成します。

検索UIを設置する

サイドバーなどに、UI を差し込むための要素と Pagefind UI の読み込みを置きます。

---
// src/components/SearchWidget.astro
---
<div id="search"></div>

<link href="/pagefind/pagefind-ui.css" rel="stylesheet" />
<script is:inline src="/pagefind/pagefind-ui.js"></script>

<script is:inline>
  window.addEventListener('DOMContentLoaded', function () {
    new PagefindUI({
      element: '#search',
      showSubResults: false,
      showImages: false,
      translations: {
        placeholder: '記事を検索...',
        zero_results: '「[SEARCH_TERM]」に一致する記事が見つかりませんでした',
      },
    });
  });
</script>

translations で日本語化できます。[SEARCH_TERM] は検索語に置換されるプレースホルダーです。

<script>is:inline を付けているのは、Astro のバンドル対象から外してそのまま出力するためです(/pagefind/... はビルド後に生成される外部アセットなので、バンドルさせない)。

インデックスの対象を絞りたいとき

デフォルトでは各ページの本文をまるごとインデックスします。ナビやサイドバーまで拾ってしまうのが気になる場合は、記事本文を囲む要素に data-pagefind-body を付けると、その範囲だけをインデックス対象にできます。

<article data-pagefind-body>
  <slot />
</article>

ハマりどころ・メモ

  • astro dev(開発サーバー)では検索は動かない。Pagefind のインデックスは build 後にしか作られないので、開発中は /pagefind/pagefind-ui.js などが 404 になる。動作確認は npm run build && npm run preview で行う。
  • 日本語は形態素解析(stemming)には非対応で、ビルド時に「ja は stemming 未対応」という注意が出る。検索自体は動くが、語幹をまたいだ一致はしない、という点は把握しておく。
  • UI の見た目は Pagefind 側の CSS クラス(.pagefind-ui__...)を上書きして調整できる。

サーバーレスのまま検索が付くので、静的ブログにはかなりおすすめです。

Pagefind, Astro