Gatsby.js 製のブログで Algolia DocSearch を導入するときにハマったこと
Algolia が提供する DocSearch を使うと、自作ブログに検索機能をつけることができます。
この記事では、Gatby.js 製のブログに DocSearch を導入したときの、ハマったポイントとその解決方法を説明します。
動作を確認した環境
- @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 のインデックスへ登録するプロパティの形式に変換します。
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:[object Object] が表示される
サイトをビルドし直して検索してみたところ、開発者ツールのコンソールに次のようなエラーが表示されてしまいました。
“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
この数字はドキュメントの階層構造にしたがっているため、今回は lvl0
と lvl1
に記事のカテゴリーと記事のタイトルを渡すようにしました。
このブログのカテゴリは今のところ「Blog」固定なので、lvl0
は固定値としています。
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
を指定します。
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
プロパティが登録されるようにします。
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}`
}
}),
},
これで、検索結果から見たいページへ遷移できるようになりました。