Back to home
Search contents

Pagefindをローカル開発時でも動作させる

Published at
399 words
2min read

Pagefindの利用例を調べると、開発時はダミーデータを渡している実装しか見つからなかったが、ダミーデータの作成やコード上の分岐が増えることが億劫だったため、開発時も本番相当のデータが表示されるようにした。

Pagefindを実際にローカルで動作させる映像

Pagefindの大まかな仕組み#

PagefindはビルドされたHTMLファイルに対して実行し、インデックスを生成することで高速な検索を実現している。

そのため、例えばAstroの場合は次のようにビルドコマンドにフックさせて、ビルド後にPagefindを実行する。

package.json
{
"scripts": {
"build": "astro build && pagefind --site dist",
}
}

ローカルで本番相当のデータを表示する実装#

次のように開発サーバー起動時にpagefindの生成を行い、結果をビルドディレクトリではなくpublicディレクトリに出力する。

package.json
{
"scripts": {
"predev": "astro build && pagefind --site dist --output-path public/pagefind",
"dev": "astro dev",
}
}

これにより開発サーバー起動時とビルド後の環境で全く同じ実装でコードが動作するようになる。

Astroでの実装例:

search.astro
<input placeholder="Search..." id="search" name="search">
<div id="search-results"></div>
<script is:inline type="module">
document.addEventListener("DOMContentLoaded", async () => {
const pagefind = await import("/pagefind/pagefind.js")
pagefind.init()
pagefind.options({
basePath: "/pagefind/",
baseUrl: "/",
indexWeight: 1,
excerptLength: 60,
})
const input = document.querySelector("#search")
const results = document.querySelector("#search-results")
const search = async (query) => {
const searchResults = await pagefind.search(query);
results.innerHTML = ""
searchResults.results.forEach(async (result) => {
const resultElement = document.createElement("div")
const data = await result.data();
resultElement.innerHTML = `
<article>
<header>
<h2 class="text-base">
<a href="${data.url}">
${data.meta.title}
</a>
</h2>
</header>
<p>
${data.excerpt}
</p>
</article>
`
results.appendChild(resultElement)
})
}
input.addEventListener("input", async (e) => {
const query = e.currentTarget.value
search(query)
});
const initValue = input.value
if (initValue) {
search(initValue)
}
})
</script>