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}`
}
}),
},
これで、検索結果から見たいページへ遷移できるようになりました。