Twitterで見かけた、Add Super Fast Search in Your Gatsby Website (Ultimate Guide for Adding Algolia’s Search to Gatsby Website) を試してみたいと思います 🙂
Okay, here’s a new post about how to add super fast search from @algolia to your @gatsby website.
— Eunjae Lee (@eunjae_lee) January 12, 2019
Nothing much to search for in my website yet, but it’s thrilling to see how instant it is!https://t.co/w6LOOXDd3v
Gatsyでブログサイトを作る
とりあえず gatsby-starter-blog に沿ってGatsbyなブログサイトを作ってみます。
↓叩いてみたら、、
npx gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog
info Creating new site from git: https://github.com/gatsbyjs/gatsby-starter-blog.git
Cloning into 'my-blog-starter'...
remote: Enumerating objects: 1348, done.
remote: Total 1348 (delta 0), reused 0 (delta 0), pack-reused 1348
Receiving objects: 100% (1348/1348), 2.93 MiB | 1.75 MiB/s, done.
Resolving deltas: 100% (745/745), done.
success Created starter directory layout
info Installing packages...
yarn install v1.3.2
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > eslint-plugin-react@7.11.1" has unmet peer dependency "eslint@^3.0.0 || ^4.0.0 || ^5.0.0".
warning "gatsby > mini-css-extract-plugin > schema-utils > ajv-errors@1.0.1" has unmet peer dependency "ajv@>=5.0.0".
[4/4] 📃 Building fresh packages...
[-/5] ⠠ waiting...
[2/5] ⠠ sharp: gyp
[-/5] ⠠ waiting...
[-/5] ⠠ waiting...
↓エラー吐いて落ちてる…w メッセージ的にはPython2がありませんってことみたいですね、、
Exit code: 1
Command: (node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)
Arguments:
Directory: /Users/eshinoha/my-blog-starter/node_modules/sharp
Output:
info sharp Downloading https://github.com/lovell/sharp-libvips/releases/download/v8.7.0/libvips-8.7.0-darwin-x64.tar.gz
prebuild-install WARN install No prebuilt binaries found (target=9.10.1 runtime=node arch=x64 platform=darwin)
gyp info it worked if it ends with ok
gyp info using node-gyp@3.8.0
gyp info using node@9.10.1 | darwin | x64
gyp ERR! configure error
gyp ERR! stack Error: Command failed: /Users/eshinoha/.pyenv/shims/python2 -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack pyenv: python2: command not found
gyp ERR! stack
gyp ERR! stack The `python2' command exists in these Python versions:
gyp ERR! stack anaconda3-4.3.1/envs/py27
gyp ERR! stack
gyp ERR! stack
gyp ERR! stack at ChildProcess.exithandler (child_process.js:273:12)
gyp ERR! stack at ChildProcess.emit (events.js:180:13)
gyp ERR! stack at maybeClose (internal/child_process.js:936:16)
gyp ERR! stack at Socket.stream.socket.on (internal/child_process.js:353:11)
gyp ERR! stack at Socket.emit (events.js:180:13)
gyp ERR! stack at Pipe._handle.close [as _onclose] (net.js:541:12)
gyp ERR! System Darwin 17.7.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/eshinoha/my-blog-starter/node_modules/sharp
手元のPythonのバージョン見てみると3.6ですよ、と。
$ python --version
Python 3.6.0 :: Anaconda 4.3.1 (x86_64)
py27っていうそれっぽいの入ってるっぽいので、そっちにしてみる
a$ conda info --envs
# conda environments:
#
py27 /Users/eshinoha/.pyenv/versions/anaconda3-4.3.1/envs/py27
root * /Users/eshinoha/.pyenv/versions/anaconda3-4.3.1
$ source /Users/eshinoha/.pyenv/versions/anaconda3-4.3.1/envs/py27/bin/activate py27
もっかいコマンド流したら、そのディレクトリ既にあるよ、と。ですよねぇw
$ npx gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog
error Directory my-blog-starter is already an npm project
上手くいったようです 🙂
$ npx gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog
info Creating new site from git: https://github.com/gatsbyjs/gatsby-starter-blog.git
Cloning into 'my-blog-starter'...
remote: Enumerating objects: 1348, done.
remote: Total 1348 (delta 0), reused 0 (delta 0), pack-reused 1348
Receiving objects: 100% (1348/1348), 2.93 MiB | 1.69 MiB/s, done.
Resolving deltas: 100% (745/745), done.
success Created starter directory layout
info Installing packages...
yarn install v1.3.2
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > eslint-plugin-react@7.11.1" has unmet peer dependency "eslint@^3.0.0 || ^4.0.0 || ^5.0.0".
warning "gatsby > mini-css-extract-plugin > schema-utils > ajv-errors@1.0.1" has unmet peer dependency "ajv@>=5.0.0".
[4/4] 📃 Building fresh packages...
✨ Done in 62.48s.
gatsby-cliをインストールして(npmよくわかってなくて–globalで入れないと動かなかったんだけど、そういうもの?)
$ npm install --global gatsby-cli
/usr/local/bin/gatsby -> /usr/local/lib/node_modules/gatsby-cli/lib/index.js
+ gatsby-cli@2.4.8
added 211 packages from 119 contributors in 10.024s
んで、gatsby develop叩いたら、メッチャ 『error Plugin gatsby-plugin-xxx returned an error』的なエラーが出てて、localhost:8000も↓こんな感じ(http://localhost:8000/___graphql はGraphQLのエディタが立ち上がってくるけど…)
ディレクトリごと消して、もっかいnpxからやり直したら↓上手くいった…w まぁイイ、先進みます!
$ gatsby develop
success open and validate gatsby-configs — 0.109 s
success load plugins — 0.419 s
success onPreInit — 11.370 s
success delete html and css files from previous builds — 0.006 s
success initialize cache — 0.019 s
success copy gatsby files — 0.080 s
success onPreBootstrap — 0.006 s
success source and transform nodes — 0.240 s
success building schema — 0.488 s
success createPages — 0.101 s
success createPagesStatefully — 0.070 s
success onPreExtractQueries — 0.006 s
success update schema — 0.354 s
success extract queries from components — 0.256 s
Generating image thumbnails [==============================] 4/4 0.0 secs 100%
success run graphql queries — 0.982 s — 9/9 9.20 queries/second
success write out page data — 0.009 s
success write out redirect data — 0.001 s
Generating image thumbnails [==============================] 11/11 0.8 secs 100%
Generating image thumbnails [==============================] 18/18 1.2 secs 100%
info bootstrap finished - 18.677 s
⢀ onPostBootstrapdone generating icons for manifest
success onPostBootstrap — 0.276 s
DONE Compiled successfully in 4312ms 17:23:12
You can now view gatsby-starter-blog in the browser.
http://localhost:8000/
View GraphiQL, an in-browser IDE, to explore your site's data and schema
http://localhost:8000/___graphql
Note that the development build is not optimized.
To create a production build, use gatsby build
ℹ 「wdm」:
ℹ 「wdm」: Compiled successfully.
とにかく画面出たしね 🙂
ということでようやく本題
流れ的には以下のような感じ。
- Algoliaのセットアップ
- GatsbyのビルドスクリプトにAlgoliaへのコンテンツアップロードを追加
- Algoliaを利用した検索UIの追加
- GatsbyのStarterブログの流れに沿っている、とのこと。
Algoliaのセットアップ
posts というインデックスを作りました
API Keysメニューから以下の情報を取得
Algoliaへのインデクシング
yarnでdotenvという環境変数的なアレと、gatsby-plugin-algoliaというそれっぽいプラグインをインストールします。なんかwarning出てるっぽいけど、とりあえず入りました。
$ yarn add dotenv gatsby-plugin-algolia
yarn add v1.3.2
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > eslint-plugin-react@7.11.1" has unmet peer dependency "eslint@^3.0.0 || ^4.0.0 || ^5.0.0".
warning "gatsby > mini-css-extract-plugin > schema-utils > ajv-errors@1.0.1" has unmet peer dependency "ajv@>=5.0.0".
[4/4] 📃 Building fresh packages...
success Saved lockfile.
success Saved 13 new dependencies.
├─ agentkeepalive@2.2.0
├─ algoliasearch@3.32.0
├─ death@1.1.0
├─ dotenv@6.2.0
├─ envify@4.1.0
├─ es6-promise@4.2.5
├─ foreach@2.0.5
├─ gatsby-cli@1.1.58
├─ gatsby-plugin-algolia@0.3.0
├─ load-script@1.0.0
├─ lodash.chunk@4.2.0
├─ reduce@1.0.1
└─ yurnalist@0.2.1
✨ Done in 36.69s.
.env に上記でAlgoliaのダッシュボードから取得した文字列を↓のxxx,yyy,zzzのところにセットします。特にAdminのkeyとかGitHub載せちゃうと、やりたい放題されてされてしまう可能性があるので、.envは.gitignoreでお願いします的な。
GATSBY_ALGOLIA_APP_ID=xxx
GATSBY_ALGOLIA_ADMIN_API_KEY=yyy
GATSBY_ALGOLIA_SEARCH_API_KEY=zzz
GATSBY_ALGOLIA_INDEX_NAME=posts
次に gatsby-config.js を編集して、プラグインの設定のところで、gatsby-plugin-algoliaにはgatsby-plugin-algolia-config.jsをロードしてね的な↓を追加してあげます。
module.exports = {
plugins: [
//...
{
resolve: `gatsby-plugin-algolia`,
options: require(`./gatsby-plugin-algolia-config.js`),
},
//...
],
}
で、その gatsby-plugin-algolia-config.js は↓こんな感じで。dotenvから読み込んだ値を使ってGraphQLゴニョゴニョ的な。
require('dotenv').config({
path: `.env`,
})
const queries = [
{
query: `
{
allMarkdownRemark {
edges {
node {
excerpt
frontmatter {
title
}
fields {
slug
}
}
}
}
}
`,
transformer: ({ data }) =>
data.allMarkdownRemark.edges.map(
({
node: {
excerpt,
frontmatter: { title },
fields: { slug },
},
}) => ({
title,
description: excerpt,
path: slug,
})
),
},
]
module.exports = {
appId: process.env.GATSBY_ALGOLIA_APP_ID,
apiKey: process.env.GATSBY_ALGOLIA_ADMIN_API_KEY,
indexName: process.env.GATSBY_ALGOLIA_INDEX_NAME,
queries,
}
で、gatsby buildしてあげます。成功したっぽい。
$ gatsby build
success open and validate gatsby-configs — 0.012 s
success load plugins — 0.335 s
success onPreInit — 2.522 s
success delete html and css files from previous builds — 0.012 s
info One or more of your plugins have changed since the last time you ran Gatsby. As
a precaution, we're deleting your site's cache to ensure there's not any stale
data
success initialize cache — 0.019 s
success copy gatsby files — 0.075 s
success onPreBootstrap — 0.005 s
success source and transform nodes — 0.106 s
success building schema — 0.411 s
success createPages — 0.061 s
success createPagesStatefully — 0.034 s
success onPreExtractQueries — 0.006 s
success update schema — 0.213 s
success extract queries from components — 0.151 s
success run graphql queries — 0.274 s — 9/9 33.12 queries/second
success write out page data — 0.006 s
success write out redirect data — 0.001 s
⢀ onPostBootstrapdone generating icons for manifest
success onPostBootstrap — 0.310 s
info bootstrap finished - 8.485 s
success Building production JavaScript and CSS bundles — 8.564 s
success Building static HTML for pages — 0.862 s — 7/7 25.64 pages/second
⠁ Algolia: 1 queries to index
⠄ index to AlgoliaAlgolia: query 0: executing query
Algolia: query 0: splitting in 1 jobs
success index to Algolia — 1.829 s
Generated public/sw.js, which will precache 10 files, totaling 273875 bytes.
info Done building in 19.866 sec
Algoliaのダッシュボードにもデータが入っていました 🙂
検索用のUI
ようやくそれっぽいところに差し掛かってきました。今回は autocomplete.js を使います。
まずは Layout.js を開いて、Searchbox をインポートします。src/components/Layout.js を開いて↓を追加。
import SearchBox from './SearchBox'
〜略〜
return (
<div
style={{
marginLeft: `auto`,
marginRight: `auto`,
maxWidth: rhythm(24),
padding: `${rhythm(1.5)} ${rhythm(3 / 4)}`,
}}
>
<SearchBox /> // んま、こんなに上じゃなくてもイイかもw
{header}
次に SearchBox.js ファイルを作成。このコードはちゃんと読んでおきたいけど、とりあえずコピペ。
import React, { Component } from 'react'
import { navigate } from 'gatsby'
import './SearchBox.css'
let algoliasearch, autocomplete, client, index
if (typeof window !== 'undefined') {
algoliasearch = require('algoliasearch/lite')
autocomplete = require('autocomplete.js')
client = algoliasearch(
process.env.GATSBY_ALGOLIA_APP_ID,
process.env.GATSBY_ALGOLIA_SEARCH_API_KEY
)
index = client.initIndex(process.env.GATSBY_ALGOLIA_INDEX_NAME)
}
class SearchBox extends Component {
componentDidMount() {
if (typeof window === 'undefined') {
return
}
autocomplete('#algolia-search-input', { hint: false }, [
{
source: autocomplete.sources.hits(index, { hitsPerPage: 5 }),
displayKey: 'title',
templates: {
suggestion: function({ _highlightResult: { title, description } }) {
return `
<p class="title">${title.value}</p>
<p class="description">${description.value}</p>
`
},
footer:
'<div class="branding">Powered by <img src="https://www.algolia.com/static_assets/images/press/downloads/algolia-logo-light.svg" /></div>',
},
},
]).on('autocomplete:selected', function(
event,
suggestion,
dataset,
context
) {
navigate(suggestion.url)
})
}
render() {
return (
<div style={{ marginBottom: '1rem' }}>
<input
type="search"
id="algolia-search-input"
placeholder="Search"
style={{
border: 'none',
}}
/>
</div>
)
}
}
export default SearchBox
↑のjsが呼んでるcssであるSearchBox.cssを同じディレクトリに配置。
で、最後にyarnで algoliasearch と autocomplete.js を追加。
$ yarn add algoliasearch autocomplete.js
yarn add v1.3.2
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
warning Pattern ["algoliasearch@^3.32.0"] is trying to unpack in the same destination "/Users/eshinoha/Library/Caches/Yarn/v1/npm-algoliasearch-3.32.0-5818168c26ff921bd0346a919071bac928b747ce" as pattern ["algoliasearch@^3.24.5"]. This could result in a non deterministic behavior, skipping.
[3/4] 🔗 Linking dependencies...
warning " > eslint-plugin-react@7.11.1" has unmet peer dependency "eslint@^3.0.0 || ^4.0.0 || ^5.0.0".
warning "gatsby > mini-css-extract-plugin > schema-utils > ajv-errors@1.0.1" has unmet peer dependency "ajv@>=5.0.0".
[4/4] 📃 Building fresh packages...
success Saved lockfile.
success Saved 3 new dependencies.
├─ algoliasearch@3.32.0
├─ autocomplete.js@0.35.0
└─ immediate@3.2.3
✨ Done in 6.66s.
そんなこんなで↓検索窓が設置されました 🙂
amzn_assoc_ad_type =”responsive_search_widget”; amzn_assoc_tracking_id =”diary045-22″; amzn_assoc_marketplace =”amazon”; amzn_assoc_region =”JP”; amzn_assoc_placement =””; amzn_assoc_search_type = “search_widget”;amzn_assoc_width =”auto”; amzn_assoc_height =”auto”; amzn_assoc_default_search_category =””; amzn_assoc_default_search_key =”javascript”;amzn_assoc_theme =”light”; amzn_assoc_bg_color =”FFFFFF”; //z-fe.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&Operation=GetScript&ID=OneJS&WS=1&Marketplace=JP