Gatsby.js 製のブログで Algolia DocSearch を導入するときにハマったこと

Blog
August 8, 2022

概要

Algolia が提供する DocSearch を使うと、自作ブログにかんたんに検索機能をつけることができます。
この記事では、Gatby.js 製のブログに DocSearch を導入したときにハマったポイントとその解決方法を説明します。

必要な環境

  • Algolia のアカウント
  • @docsearch/react v3
  • Gastby.js v4

ハマったこと1:Algolia Crawler が利用可能になるまでに時間がかかりそう

Algolia を使って検索機能を実装する場合、事前に Algolia の検索インデックスにブログのコンテンツを登録する必要があります。
自前で登録する仕組みを用意する代わりに、Algolia Crawler というサービスを利用すると、定期的にインデックスに登録できます。
DocSearch を導入する場合、Algolia Crawler も同時に利用できますが、申請が必要であり、チェックリストに該当していなければなりません。

技術ブログも申し込みできる対象になっていますが、利用可能になるまでには時間がかかりそうでした。
そのため、今回は自前で Algolia のインデックスを自前で登録することにしました。

Gatsby.js 製のブログの場合、gastby-plugin-aloglia を導入すると、登録処理の部分を実装する必要がなさそうだったため、これを使うことにしました。
gatsby-config.js を使うとサイトのビルド時にサイト内の情報を Algolia のインデックスに自動で登録するようになります。

導入はかんたんで、npm でインストールした後に gatsby-config.js に設定を追記します。
Algolia の環境設定は、環境変数から読み込むようにします。
このブログは Netlify でホスティングしているため、忘れずに Netlify の環境設定にも設定します。

queries の部分では、登録対象となる記事のコンテンツを抽出するクエリを指定します。
また、transformer で、抽出したコンテンツを Algolia のインデックスへ登録するプロパティの形式に変換します。

gatsby-config.js
module.exports = {
  // ...,
  plugins: [
    {
      resolve: `gatsby-plugin-algolia`,
      options: {
        appId: process.env.GATSBY_ALGOLIA_APP_ID,
        apiKey: process.env.ALGOLIA_API_KEY,
        indexName: process.env.GATSBY_ALGOLIA_INDEX_NAME,
        queries: [
          {
            query: `{
              allMdx {
                edges {
                  node {
                    excerpt
                    fields {
                      slug
                    }
                    frontmatter {
                      title
                      date(formatString: "YYYY-MM-DD")
                      tags
                    }
                  }
                }
              }
            }`,
            transformer: ({ data }) =>
              data.allMdx.edges.flatMap(({ node }) => {
                return {
                  id: node.fields.slug,
                  content: node.excerpt,
                  title: node.frontmatter.title,
                  publishedAt: new Date(node.frontmatter.date),
                  tags: node.frontmatter.tags,
                }
              }),
          },
        ],
        chunkSize: 10000,
      },
    },
  ],
  // ...
}

あとはGetting Started を参考に、ヘッダーを表示するコンポーネントに DocSearch の検索窓のコンポーネントを設置すれば、検索ボックスが表示されます。

ハマったこと 2:“Uncaught (in promise) TypeError: Cannot read property ‘lvl0’ of undefined” が表示される

サイトをビルドし直して検索してみたところ、開発者ツールのコンソールに次のようなエラーが表示されてしまいました。

“Uncaught (in promise) TypeError: Cannot read property ‘lvl0’ of undefined”

どうやら DocSearch で検索するにはインデックスの属性に hierarchy というプロパティが必要で、Algolia Crawler はこのプロパティを自動で登録しているようでした。
そのため、gastby-plugin-algolia のインデックスへ登録するプロパティの形式に変換する箇所で、hierarchy プロパティが登録されるようにします。

hierarchy プロパティの属性には、lvl0 から lvl6 まで指定できます。
Ref. recordProps API Reference

この数字はドキュメントの階層構造にしたがっているため、今回は lvl0lvl1 に記事のカテゴリーと記事のタイトルを渡すようにしました。
このブログのカテゴリは今のところ「Blog」固定なので、lvl0 は固定値としています。

gatsby-config.js
            transformer: ({ data }) =>
              data.allMdx.edges.flatMap(({ node }) => {
                return {
                  id: node.fields.slug,
                  // ...
+                  hierarchy: {
+                    lvl0: "Blog",
+                    lvl1: node.frontmatter.title
+                  },
                }
              }),
          },

Algolia のインデックスが生成し直した後にもう一度検索し直してみると、「Uncaught 〜」エラーは消えて検索結果が表示されるようになりました。

ハマったこと 3:検索結果の一覧に「#」だけが表示されてしまう

検索結果は表示されるようになったものの、一覧には「#」だけが表示されています。

画面キャプチャ:検索結果に「#」だけが表示されている

調べたところ、インデックスに type というプロパティでどの値を一覧のタイトル部分表示するかを指定する必要があるようでした。
そのため、gastby-plugin-algolia のインデックスへ登録するプロパティの形式に変換する箇所で、type プロパティが登録されるようにします。
今回は記事タイトルを表示したいため、記事タイトルである lvl1 を指定します。

gatsby-config.js
            transformer: ({ data }) =>
              data.allMdx.edges.flatMap(({ node }) => {
                return {
                  id: node.fields.slug,
                  // ...
                  hierarchy: {
                    lvl0: "Blog",
                    lvl1: node.frontmatter.title
                  },
+                  type: "lvl1",
                }
              }),
          },

もう一度サイトをビルドしてインデックスを登録し直すと、ぶじ検索結果の一覧に記事タイトルが表示されるようになりました。

画面キャプチャ:検索結果に記事タイトルが表示されている

ハマったこと 4:検索結果の一覧をクリックしても、目的のページに遷移しない

検索一覧が表示されるようになったものの、一覧をクリックしても目的のページに遷移しません。
この原因は、url というプロパティがインデックスにないためでした。
そのため、これまでと同様に gastby-plugin-algolia の設定で url プロパティが登録されるようにします。

gatsby-config.js
            transformer: ({ data }) =>
              data.allMdx.edges.flatMap(({ node }) => {
                return {
                  id: node.fields.slug,
                  // ...
                  hierarchy: {
                    lvl0: "Blog",
                    lvl1: node.frontmatter.title
                  },
                  type: "lvl1",
+                  url: `${baseUrl}${node.fields.slug}`
                }
              }),
          },

これで、検索結果から見たいページに遷移できるようになりました。

まとめ

格好いい検索機能を自ブログに導入できたぞ!