pagefindは、大規模なサイトでも優れたパフォーマンスを発揮する、静的サイト向け全文検索ライブラリです。
UIも提供されているので、サクッと導入することできます。
今回はAstroのプロジェクトにpageindexを導入してみます。
pagefindのインストール
まずはpagefind
と@pagefind/default-ui
というパッケージをインストールしていきます。
pnpmやyarnを使っている人は適宜読み替えてください。
$ npm install pagefind @pagefind/default-ui
検索用コンポーネント
デフォルトで用意されているUIがあるので、そちらを使って検索用のUIコンポーネントを実装します。
---
import "@pagefind/default-ui/css/ui.css";
---
<div id="search"></div>
<script>
import { PagefindUI } from "@pagefind/default-ui";
new PagefindUI({
element: "#search",
// element以外のオプションは任意で設定
});
</script>
作成したコンポーネントは任意のファイルでインポートしてください。
今回は、src/pages/index.astroに追加しておきます。
---
...
import Sarch from '@components/Search.astro'
---
<Layout>
<Search />
...
</Layout>
TypeScriptを使用してる場合、@pagefind/default-uiには型定義が存在しないため、build時にエラーが発生します。そのため、下記をenv.d.tsに追加しておいてください。
declare module "@pagefind/default-ui" {
declare class PagefindUI {
constructor(opts: {
element?: string | HTMLElement,
bundlePath?: string,
pageSize?: number,
resetStyles?: boolean,
showImages?: boolean,
showSubResults?: boolean,
excerptLength?: number,
processResult?: any,
processTerm?: any,
showEmptyFilters?: boolean,
debounceTimeoutMs?: number,
mergeIndex?: any,
translations?: any,
autofocus?: boolean,
sort?: any,
})
}
}
検索用indexの作成
最後に検索用のindexを作成します。
$ npm run build
Astroでは、dist配下にbuild後のファイルが作成されます。
そのため、distをオプションに設定し、pagefindの検索用indexを作成する下記コマンドを実行します。
また、生成されるindexはbuild後のHTMLファイルのlang属性に基づいて、言語が判定されるため、build前にlang属性を統一しておくことをおすすめします。
複数言語での検索ができないわけではないので、複数言語で検索機能を実装したい場合は公式サイトを参考にしてみてください。
$ npx pagefind --site dist
本番環境へのデプロイ時にbuildと同時にindex作成できるようにしておきたい(かつ毎回build→indexの作成を行うのは面倒くさい)ので、buildコマンドを実行したタイミングでindexも作成できるようにしておきましょう。
{
"scripts": {
"build": "astro build && pagefind --site dist"
}
}
これでpagefindを使った全文検索の準備は完了です。
$ npm run preview
実際にbuild後のプロジェクトを確認してみると全文検索が機能していることが確認できると思います。
まとめ
pagefindを使えば手軽に全文検索機能を実装することができました。
今回は最小限の部分しか解説していないですが、このほかにも様々なオプションが用意されています。
公式サイトを参考にしながらぜひ好みにカスタマイズしてみてください。
日本語の検索でも基本的に問題なく、動作も非常に軽く使い勝手が良いため、今後もし静的サイトに全文検索を実装するとなったら使いたいと思えるライブラリでした。
ただ、若干公式サイトを見ても分かりにくかったり、ググった時の情報が少ないので、詰まった時は苦労するなぁーとは思いますが、、