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

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を使用すれば、かんたんに検索のページを作成することができます。


参考記事