Pagefindをローカル開発時でも動作させる
399 words
2min read
Pagefindの利用例を調べると、開発時はダミーデータを渡している実装しか見つからなかったが、ダミーデータの作成やコード上の分岐が増えることが億劫だったため、開発時も本番相当のデータが表示されるようにした。
Pagefindの大まかな仕組み
PagefindはビルドされたHTMLファイルに対して実行し、インデックスを生成することで高速な検索を実現している。
そのため、例えばAstroの場合は次のようにビルドコマンドにフックさせて、ビルド後にPagefindを実行する。
{ "scripts": { "build": "astro build && pagefind --site dist", }}
ローカルで本番相当のデータを表示する実装
次のように開発サーバー起動時にpagefindの生成を行い、結果をビルドディレクトリではなくpublicディレクトリに出力する。
{ "scripts": { "predev": "astro build && pagefind --site dist --output-path public/pagefind", "dev": "astro dev", }}
これにより開発サーバー起動時とビルド後の環境で全く同じ実装でコードが動作するようになる。
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>