Netlifyで運用しているGatsbyを使ったblogにalgolia検索を導入する


algoliaは非常に高速なサイト内検索を提供してくれるサービスです。無料プランがあり、JavaScript主体のサイトでも簡単に導入できます。ReactなどOSSのドキュメントサイトに導入されているケースも多いです。

algolia検索に以前から興味があったのでこのブログに導入してみました。

このサイトと実装のalgolia検索実装の流れについて

CrudzooはGatsbyのテーマ機能を使ってカスタマイズし、githubのプライベートレポジトリに設置、Netlifyと連携してNetlifyにdeployしています。

  1. algoliaにアカウント登録する
  2. Gatsbyサイトにalgolia検索を導入する
  3. Netlifyにalgoliaの環境変数を設定する

上記の手順で実装しました。すでにGatsbyでサイト公開しているような状態なら1日かからない程度の作業量です。

algoliaにアカウントを作成する

algolia

名前とメールアドレス、所属組織の登録が必要です。あるいはGithub、Googleアカウントでもログインできます。

Gatsbyサイトにalgoliaプラグインを導入する

Gatsby公式サイトに手順があるためその通りに進めます。

Adding Search with Algolia

.envはローカル開発時のみ使う

下記の環境変数はローカル開発時は.envに書いてデバッグし、githubにはpushしません。

GATSBY_ALGOLIA_APP_ID=insertValue
GATSBY_ALGOLIA_SEARCH_KEY=insertValue
ALGOLIA_ADMIN_KEY=insertValue

これらはNetlifyの環境変数に設定します。プライベートリポジトリなら問題ないかもしれませんが、間違えてオープンにした時にAPI Keyも流出すると困ります。gitignoreなどに.envも追加しましょう。

.env

.envをすでに使用してgitにある場合は.env.developmentなどを作成して使います。

algolia用のquery

Gatsbyに使用しているpluginやそのバージョンなどでqueryの内容は変わります。実際に記事表示に使用しているqueryをカスタマイズするのが早いです。このサイトの場合は下記にしました。

const blogQuery = `{
  blog: allMdx(filter: {
    fileAbsolutePath: {regex: "/blog/"}
  }) {
	  edges {
	     node {
        parent {
          ... on File {
            relativeDirectory
          }
        }
        objectID: id
        frontmatter {
          title
          spoiler
          date(formatString: "MMM D, YYYY")
          tags
        }
        excerpt(pruneLength: 5000)
      }
	}
  }
}`
const flatten = arr =>
  arr.map(({ node: { frontmatter, ...rest } }) => ({
    ...frontmatter,
    ...rest,
  }))
const settings = { attributesToSnippet: [`excerpt:20`] }
const queries = [
  {
    query: blogQuery,
    transformer: ({ data }) => flatten(data.blog.edges),
    indexName: `Blogs`,
    settings,
  },
]

module.exports = queries

検索対象にする記事を取得できるqueryなら問題ありません。queryが不明の場合はgatsby developでgraphql(localhost:8000/___graphql)にアクセスして左サイドメニューから試行錯誤します

検索用コンポネントの作成

公式サイトの手順に従い、Search用のコンポネントを作成します。styled-componentを使用していない場合はstyles.jsとアイコン部分の修正が必要です。また、検索ボックス外をクリックする時に検索部分を非表示にするためのuseClickOutsideは、下記を変わりに使用しました。

useOnClickOutside

こちらで紹介されているコードです。

import * as React from "react"

export function useOnClickOutside(ref, handler) {
  React.useEffect(() => {
    const listener = event => {
      if (!ref.current || ref.current.contains(event.target)) {
        return
      }
      handler(event)
    }
    document.addEventListener("mousedown", listener)
    document.addEventListener("touchstart", listener)

    return () => {
      document.removeEventListener("mousedown", listener)
      document.removeEventListener("touchstart", listener)
    }
  }, [ref, handler])
}

元々のコードだとエラーが出た部分があったので置き換えました。検証していませんが単純にコピペを失敗していた可能性があります。

  <div ref={ref} style={{ position: "relative" }}>
    <InstantSearch />

InstantSearchの上部にdivを起き、refを設定します。ほぼ公式のままですが上記の修正を加えた後のコードは下記にあります。

https://github.com/Hidekazoo/gatsby-crudzoo/tree/add-algolia/src/components/search

layout.tsxでsearchIndicesは設定しています

const searchIndices = [{ name: `Blogs`, title: `検索結果`, hitComp: `PostHit` }]

algoliaに記事データを登録する

Searchコンポネントの作成が終了したら、.envにalgoliaのAPI情報を書き、gatsby buildします。成功するとalgoliaダッシュボードのIndicesにqueryで取得した記事データが全て登録されます。

ここまでの作業でalgolia検索がローカル環境で動くようになっています。

Netlifyに設定を追加する

gitにpushする前にNetlifyにalgolia用のAPIを設定します。

Site settings > Build & deploy > Environment > Environment variables

.envに設定したキーを登録します。

  • ALGOLIA_ADMIN_KEY
  • GATSBY_ALGOLIA_APP_ID
  • GATSBY_ALGOLIA_SEARCH_KEY

また、algolia関係ありませんがfs-eventのエラーなどローカルでbuildして成功するのにNetlifyでは失敗するときがあります。その場合はnodeのバージョンも追加します。

  • NODE_VERSION

ローカル環境でnode -vコマンドを打ち、同じバージョンの数値を指定します。Netlify上でもbuildが正常に終了すればdeploy先で検索機能が動きます。

その他

作業中に遭遇したあれこれ。

  • 変数名 not defined

developは成功するがbuild時に出るエラー。原因はmdx用pluginでした。記事中に$マークとが続とbuild時だけ変数扱いとなります。該当のmarkdownファイルから文字列を消去するなどで対応。

  • ローカルでbuildできるがnetlifyでbuildできない

nodeバージョンを揃えること。ファイル名の大文字と小文字が間違っていないかの確認。ファイル名hitComp.jsとして

import {} from 'hitcomp'

これがmacだとimportできlinuxではできません。コピペしすぎたために起きた失敗でした。

次の課題

algoliaの導入はできました。アクセス数と記事数的に無料枠から出ることもないとは思います。様子を見つつ、スタイルや検索内容の調整をしていく予定です。