静的サイトにJavaScriptだけで検索機能を追加する方法|JSONを使った実装例

この記事は約3分で読めます

こんにちは、 @Manabu です。

静的サイトを運営していて記事数が増えてくると、目的の記事を探すための検索機能が欲しくなります。

ただ、検索のためだけにLambdaやデータベースを用意するのは、少し大きな構成になってしまいます。

今回は、ビルド時に検索用JSONを作り、ブラウザのJavaScriptだけでサイト内検索を行う方法について紹介します。

この記事は、以下のような方におすすめです。

こんな方におすすめ

  • 静的サイトに検索機能を追加したい
  • 検索用のサーバーやデータベースを用意したくない
  • 数十件から数百件程度の記事を管理している

検索用JSONを生成する

サイトを生成するとき、公開記事から次の情報を抽出します。

  • タイトル
  • description
  • URL
  • 大分類
  • カテゴリー
  • タグ
  • 投稿日と更新日

これをsearch-index.jsonとして出力します。

[
  {
    "title": "CloudFrontとS3の設定方法",
    "description": "静的サイトの構成を紹介します。",
    "url": "/aws/example/",
    "category": "AWS",
    "tags": ["CloudFront", "S3"]
  }
]

検索フォームを作成する

検索ページへフォームと結果表示用の要素を用意します。

<form id="search-form">
  <label for="search-input">記事を検索</label>
  <input id="search-input" type="search" required>
  <button type="submit">検索</button>
</form>

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

ブラウザで絞り込む

検索ページを開いたときにJSONを取得し、入力したキーワードがタイトル、説明、カテゴリー、タグに含まれる記事を表示します。

const form = document.querySelector('#search-form');
const input = document.querySelector('#search-input');
const status = document.querySelector('#search-status');
const results = document.querySelector('#search-results');

let posts = [];

fetch('/search-index.json')
  .then(response => {
    if (!response.ok) throw new Error('検索データを取得できませんでした。');
    return response.json();
  })
  .then(data => {
    posts = data;
  })
  .catch(error => {
    status.textContent = error.message;
  });

form.addEventListener('submit', event => {
  event.preventDefault();

  const keyword = input.value.trim().toLocaleLowerCase('ja-JP');
  if (!keyword) return;

  const matched = posts.filter(post => {
    const target = [
      post.title,
      post.description,
      post.category,
      ...(post.tags || []),
    ].join(' ').toLocaleLowerCase('ja-JP');

    return target.includes(keyword);
  });

  status.textContent = `${matched.length}件の記事が見つかりました。`;
  results.replaceChildren();

  for (const post of matched) {
    const link = document.createElement('a');
    link.href = post.url;
    link.textContent = post.title;
    results.append(link);
  }
});

検索結果の生成にinnerHTMLを使う場合は、JSON内の文字列をそのままHTMLとして挿入しないようにしてください。上記ではtextContentを使い、記事タイトルを文字列として追加しています。

この方法では、Lambda、API Gateway、データベースなどを用意する必要がありません。

URLのクエリから検索する

/search/?q=CloudFrontのようなURLに対応する場合は、URLSearchParamsから検索文字列を取得できます。

const params = new URLSearchParams(window.location.search);
const initialKeyword = params.get('q') || '';
input.value = initialKeyword;

タグのリンクから検索ページへ移動させる場合にも利用できます。

向いているサイト

  • 数十件から数百件程度の記事サイト
  • 更新時に静的ファイルを再生成できるサイト
  • 複雑な全文検索を必要としないサイト

記事数や本文データが非常に多くなるとJSONのサイズも大きくなるため、その段階で外部検索サービスなどを検討します。

まとめ

今回は、検索用JSONとJavaScriptを使って、静的サイトに検索機能を追加する方法について紹介しました。

記事数がそれほど多くなければ、検索用のサーバーやデータベースを用意しなくても十分に対応できます。

静的サイトの構成を大きくせずに検索機能を追加したい方は、ぜひ参考にしてみてください。