+++

サイトの運営期間が長くなり記事の数が増えてくると、読者が「以前読んだあの記事、どこだったかな?」と過去の情報を探すのが難しくなります。
そこで必須となるのが、サイト内検索機能 の実装です。

WordPressなどの動的CMSとは異なりHugoは静的サイトであるため、検索機能の導入は少し難しそうに思えるかもしれません。しかし今回は、サーバー(バックエンド)を使わずにブラウザ上のJavaScriptだけで完結する 「クライアントサイド検索」 を構築します。
非常に軽量で強力な検索ライブラリ Fuse.js を活用することで、外部サービスに依存しない爆速なサイト内検索機能が驚くほど簡単に作れます!


1. 検索用のデータ (index.json) を作る

まずは、サイト内の全記事のデータをJSON形式で出力するようにします。
これが「検索データベース」の役割を果たします。

hugo.toml の設定

# hugo.toml
[outputs]
  home = ["HTML", "JSON", "RSS"]

テンプレートの作成

themes/my-tutorial-theme/layouts/index.json を作成します。
(※Hugo v0.145以前の旧仕様では layouts/_default/index.json に配置していました)

{{- $.Scratch.Add "index" slice -}}
{{- range .Site.RegularPages -}}
    {{- $.Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

これで、http://localhost:1313/index.json にアクセスすると、全記事のデータが表示されるようになります。


2. 検索ページ (search.html) を作る

検索ボックスを表示するページを作ります。

記事ファイル

content/search.md を作成します。

+++
title = "Search"
layout = "search"
build = { list = "never" }  # 記事一覧には表示しない隠しページにする
+++

レイアウトファイル

themes/my-tutorial-theme/layouts/search.html を作成します。
(※こちらも旧仕様では layouts/_default/search.html でした)
ここで Fuse.js自作のスクリプト を読み込みます。

{{ define "main" }}
<div class="search-container">
    <h1>{{ .Title }}</h1>
    
    <div class="search-box">
        <input type="text" id="search-input" placeholder="Type here to search...">
    </div>

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

<!-- Fuse.js (検索ライブラリ) の読み込み -->
<script src="https://cdn.jsdelivr.net/npm/fuse.js@6.6.2"></script>
<!-- 自作スクリプトの読み込み -->
{{ $search := resources.Get "js/search.js" | resources.Minify | resources.Fingerprint }}
<script src="{{ $search.RelPermalink }}"></script>
{{ end }}

> **【注意】ファイルの置き場所に注意!**
> `resources.Get` を使う場合、そのファイルは `static` ではなく **`assets`** フォルダに入れる必要があります。
> `themes/my-tutorial-theme/assets/js/search.js` に配置されているか確認してください。

3. 検索ロジック (search.js) を書く

最後に、実際に検索を行うJavaScriptを書きます。
themes/my-tutorial-theme/static/js/search.js を作成します。

(コードが長いので要点だけ解説します。ファイルの中身を見てみてください!)

  1. ページの読み込み完了時に /index.json を取得(Fetch)します。
  2. Fuse.js を初期化します(タイトルや本文を検索対象に設定)。
  3. input イベント(文字入力)を検知して、fuse.search(query) で検索を実行します。
  4. 結果をHTMLに変換して表示します。

快適な検索機能で読者の利便性を高めよう

複雑なバックエンドサーバーや外部の有料検索サービス(Algoliaなど)を契約しなくても、HugoのJSON出力機能と Fuse.js を組み合わせるだけで、実用十分なサイト内検索機能が無料で構築できます。
/search/ にアクセスして、日本語のキーワード設定でもサクサクと高速に検索結果が表示されることを確認してみてください。

「読みたい記事、探している情報がすぐに見つかる」ユーザーフレンドリーなサイトへとまた一歩進化しましたね!🚀