コンテンツにスキップする

Pagefind を使ってみました

投稿時刻2024年4月27日 14:27

Pagefind

Pagefind を使ってみました。
Pagefind はフロントエンドだけで検索の機能を処理することができるので、静的サイトで使うと便利です。
自分の場合、 Astro 製のブログに Pagefind を用いて、検索のページを作成しました。

目次

Pagefind をインストールする

Pagefind を npm などのコマンドでインストールします。

$ npm install pagefind

Pagefind でインデックスのファイルを生成する

Pagefind のコマンドを実行して、インデックスのファイルを生成します。
--site コマンドライン引数には、ビルドした静的サイトのファイルが格納されているディレクトリのパスを指定します。
Astro で静的サイトをビルドした場合、デフォルトでは dist ディレクトリにファイルが出力されますので、 --site コマンドライン引数に dist ディレクトリを指定してます。

$ npx pagefind --site "dist"
Running Pagefind v1.1.0 (Extended)
Running from: [REDACTED]
Source:       "dist"
Output:       "dist\\pagefind"

[Walking source directory]
Found 40 files matching **/*.{html}

[Parsing files]
Did not find a data-pagefind-body element on the site.
 Indexing all <body> elements on the site.

[Reading languages]
Discovered 1 language: en

[Building search indexes]
Total:
  Indexed 1 language
  Indexed 40 pages
  Indexed 1364 words
  Indexed 0 filters
  Indexed 0 sorts

Finished in 0.328 seconds

Astro でビルドをして Pagefind でインデックスのファイルを生成する

Astro で静的サイトをビルドして、 HTML などのファイルを生成します。
それから HTML などの生成されたファイルを Pagefind で解析して、インデックスのファイルを生成します。
最後に Astro のプレビューのコマンドを実行して、サイトの確認をします。

$ npx astro build
$ npx pagefind --site "dist"
$ npx astro preview

Pagefind で生成されるファイルについて

Pagefind でインデックスのファイルを生成した場合、下記のようにファイルが生成されます。
dist ディレクトリ直下に pagefind というディレクトリが作成されます。

fragmentindex のディレクトリには、たくさんのファイルが生成されました。
Pagefind の UI で使用される pagefind-ui.js などのファイルも生成されました。

$ tree ./dist/pagefind
./dist/pagefind
|-- filter
|   `-- ja_ccb734b.pf_filter
|-- fragment
|   |-- ...
|   `-- ja_ffed1c7.pf_fragment
|-- index
|   |-- ...
|   `-- ja_f6bb4db.pf_index
|-- pagefind-entry.json
|-- pagefind-highlight.js
|-- pagefind-modular-ui.css
|-- pagefind-modular-ui.js
|-- pagefind-ui.css
|-- pagefind-ui.js
|-- pagefind.ja_3e1987ffbf.pf_meta
|-- pagefind.js
`-- wasm.unknown.pagefind

3 directories, 174 files

Astro で Pagefind の UI を表示する

Astro で Pagefind の UI を表示します。
src/pages ディレクトリ内に search.astro などの名前で適当にファイルを作成します。
それから下記のようにコードを記述します。

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

<script is:inline>
	document.addEventListener("DOMContentLoaded", () => {
		new PagefindUI({ element: "#search" });
	});
</script>

<div id="search"></div>

Astro を使用しておりますので、 script 要素には is:inline 属性の記述を追加しております。
is:inline 属性の記述が不要な場合には削除してください。

ファイルを作成して、 Pagefind の UI を表示するコードを記述したら、再度 Astro でビルドして、 Pagefind でインデックスのファイルを生成します。
それから Astro のプレビューのコマンドを実行し、 Pagefind の UI の挙動を確認します。

日本語で検索できるようにする

最初は html 要素の lang 属性に en を指定していたため、日本語では検索できませんでした。
そこで html 要素の lang 属性に ja を指定したところ、日本語で検索できるようになりました。

<html lang="ja">

日本語で検索する際に、全角空白も検索クエリに含まれてしまう

Pagefind で検索する際に、区切り文字として全角空白を入力した場合、その全角空白では区切られずに、一つの単語として処理されてしまいます。
検索時に期待されている処理としては、全角空白も区切り文字として認識されるような処理だと思います。

一応、半角空白で単語を区切れば、別々の単語として処理されます。
なので、ユーザの入力があった場合に、全角空白を半角空白に置換するような処理を挟めばいいと思います。

Pagefind の UI のフォントを変更する

Pagefind の UI のスタイルは変更することができます。
CSS の変数を使用することで、 Pagefind の UI の色やフォントなどを変更することができます。

Using the Default UI | Pagefind — Static low-bandwidth search at scale

Pagefind で生成された CSS のファイルには :root セレクタに CSS の変数が定義されていました。

:root {
	--pagefind-ui-scale: .8;
	--pagefind-ui-primary: #393939;
	--pagefind-ui-text: #393939;
	--pagefind-ui-background: #ffffff;
	--pagefind-ui-border: #eeeeee;
	--pagefind-ui-tag: #eeeeee;
	--pagefind-ui-border-width: 2px;
	--pagefind-ui-border-radius: 8px;
	--pagefind-ui-image-border-radius: 8px;
	--pagefind-ui-image-box-ratio: 3 / 2;
	--pagefind-ui-font: system, -apple-system, "BlinkMacSystemFont", ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", "Ubuntu", "arial", sans-serif;
}

下記のように記述することで Pagefind の UI のフォントを変更することができます。
下記の記述でも is:inline 属性を記述していますので、不要な場合には削除してください。

<style is:inline>
	:root {
		--pagefind-ui-font: "BIZ UDPGothic", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
	}
</style>

検索結果の表示件数を変更する

pageSize オプションを変更すると、検索結果の表示件数を変更することができます。
デフォルトでは表示件数は 5 件となっていますが、 10 件に変更しました。

<script is:inline>
	document.addEventListener("DOMContentLoaded", () => {
		new PagefindUI({
			element: "#search",
			pageSize: 10,
		});
	});
</script>

サブリザルトを有効化する

サブリザルトを有効化すると、検索結果に 3 件までの見出しが表示されるようになります。
デフォルトではサブリザルトは無効化されております。

Showing multiple results per page | Pagefind — Static low-bandwidth search at scale

<script is:inline>
	document.addEventListener("DOMContentLoaded", () => {
		new PagefindUI({
			element: "#search",
			showSubResults: true
		});
	});
</script>

記事のページだけをインデックスさせる

Pagefind で記事のページだけをインデックスさせる場合、 data-pagefind-body 属性や data-pagefind-ignore 属性を特定の要素に記述します。
そうすることで、タグのページなどをインデックスから除外することができます。

Configuring what content is indexed | Pagefind — Static low-bandwidth search at scale

記事のページのインデックスさせたい箇所に data-pagefind-body 属性を記述します。
下記のように記述することで、記事のタイトルや本文などだけをインデックスに含めることができます。

data-pagefind-body 記述している要素の子要素で除外したい箇所がある場合、その要素に data-pagefind-ignore 属性を記述します。

<main data-pagefind-body>
	<h1>タイトル</h1>
	<article>
		<p>本文</p>
	</article>
	<ul data-pagefind-ignore="all">
		<li>
			<span>タグ1<span>
		</li>
		<li>
			<span>タグ2<span>
		</li>
		<li>
			<span>タグ3<span>
		</li>
	</ul>
</main>

data-pagefind-body 属性を記述したら、 Pagefind のインデックスを生成するコマンドを実行します。
そうすると、下記のように data-pagefind-body 属性が記述された要素が見つかったとコンソールに表示されます。

[Parsing files]
Found a data-pagefind-body element on the site.
 Ignoring pages without this tag.

data-pagefind-body 属性を記述した場合、 data-pagefind-body 属性を記述していない他のページはインデックスされなくなります。
記事のページだけに data-pagefind-body 属性を記述してしまえば、タグのページなどはインデックスに含まれなくなります。

Removing pages from Pagefind’s index
Once a data-pagefind-body attribute exists on any page of your site, any pages without this attribute will not be indexed.
As such, the best way to remove pages is by adding data-pagefind-body to the pages you would like to index.

おわりに

Pagefind を使ってみました。
Astro などで静的サイトをビルドする場合に、 Pagefind を使用すれば、かんたんに検索のページを作成することができます。


参考記事