Gatsby+microCMSで手を打つ
Intro
Angular…、そしてNext.js…。
SPAを開発しているのにSSRを考えないとイカン…なことが多くAngularから流れてくる人多いと思う。そんなこともあってNext.jsを始めたがページリロードすると404エラーとか…、それを解決するのにFunctionをとか導入して関数を書いてサーバー側で…とかもういいかげんにしてと思ってきた。
Nuxtにするか、とまた本買ってしまったが調べてみるとこれでもどうも同じことになるようで無駄な出費またまたあーもーとかなってるところにGatsbyって来て、情報が少ないものの「URLを直叩きしようがリロードしようが、404エラーが帰ってくることはなくなります」(Reactの最強フレームワークGatsby.jsの良さを伝えたい!!)
ということなので賭けてみる。
Gatsbyプロジェクト作成
- node インストール
- git インストール
- gatsby-cli インストール
npm install --global gatsby-cli
- プロジェクト作成
gatsby new <プロジェクト名>
(gatsby-default-starterがあたる) - プロジェクトフォルダに移動してローカル環境立ち上げ
gatsby develop
-
http://localhost:8000 にアクセス
フォルダ構造をみてみる。
とってもNextと似ているのでつい最近の苦労は無駄でなかったと救われる。
gatsby-config.js
というファイルがプラグイン管理
その他のgatsby-ほにゃらら.jsファイルはデフォルトでカラ。
package.jsonを見てみる
{
"name": "gatsby-starter-default",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"dependencies": {
"gatsby": "^2.20.12",
"gatsby-image": "^2.3.1",
"gatsby-plugin-manifest": "^2.3.3",
"gatsby-plugin-offline": "^3.1.2",
"gatsby-plugin-react-helmet": "^3.2.2",
"gatsby-plugin-sharp": "^2.5.3",
"gatsby-source-filesystem": "^2.2.2",
"gatsby-transformer-sharp": "^2.4.3",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-helmet": "^6.0.0"
},
"devDependencies": {
"prettier": "2.0.4"
},
・・・以下略・・・
reactから派生したんだなとわかる。
microCMSとの連携
ヘッドレスCMSはmicroCMSが評判が良いようなのでこれで。
- microCMS用のプラグインをインストールする。
$ yarn add gatsby-source-microcms
- つぎに
gatsby-config.js
を編集する
・・・前略・・・
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
// 追加↓
{
resolve: "gatsby-source-microcms",
options: {
apiKey: "X-API-KEY",
serviceId: "guitar-club",
endpoint: "news",
},
},
// 追加↑
],
}
micorCMSのAPI-KEY, サービスID、エンドポイントをoptions:{...}に書けばよいようである。書かないでgatsby develop
してもエラーでたち上がらない。
なのでmicroCMSの設定を。
microCMS準備
microCMSのサイトはこちら→ https://microcms.io/
ここでアカウント作成してログイン。
ここでは医療系情報サイトをイメージして、一般情報、患者さん向け、医師向け、といったカテゴリーがあり、それぞれのカテゴリーに多くの情報ページがぶらさがる単純な2階層のWebサイトをイメージして作ってみる。
まずはサービス名とサービスIDを入力。サービスIDはエンドポイントのサブドメインになる(※ https://<サービス名>.microcms.io/ となる)。自分のプロジェクト名とかサイト名がいいだろうわかりやすいし。たとえばhogehoge.jpというサイトだったらhogehogeとか。
次にコンテンツを作成する。まずはカテゴリーというAPIを作る。左端メニューの「コンテンツ ✙」の✙をクリック。
患者向けカテゴリーとしてpatientsと入力した。公開ボタンをクリック
ほかのカテゴリーも同様に追加していく。ここでは医師向けとしてdoctors、一般情報としてbasicsと。
次にカテゴリーの下にぶらさげるコンテンツを作っていく。
またコンテンツ✙をクリックして、記事コンテンツ、articlesと入力
種類とあるが、だいたい良く知ったようなものだ。テキストフィールドとかテキストエリアとか。ブログみたくリッチに編集したかったらリッチエディタで画像やリンクを張ったりもできる。カラーピッカーはまだないようだが・・・
最後にカテゴリーフィールドをつくる。種類は「複数コンテンツ参照」というのを選び、さっき作った「カテゴリー」APIを選んで決定。
GET /articles/{CONTENT_ID}とあるが、つまりエンドポイントはhttps://<サービスID>.microcms.io/api/v1/articles/
になる。gatsbyの場合、gatsby-config.js
のendpoint:に"articles"とだけ書けばいいが、Next.jsなどではgetInitialProps()で
const res = await axios.get(`https://<サービスID>.microcms.io/api/v1/articles/`,
key
)
のようにしなければならないようである。参考:Next.js + microCMS + NetlifyでJAMstackな世界に入門する
APIキーもここに載ってる。表示ボタンをクリックして表示させてコピーして使う。
次にAPI設定をクリック。
ここでさっき作ったフィールドを削除、追加、編集できる。なので最初は適当にタイトルとか内容(コンテンツ)とかとかまあ適当に・・・
あとはブログみたく中身をいれるだけ。入力したら公開をクリック。
「カテゴリー」フィールドは患者さん向けのpatientsにした(入力するときpatients, doctors, basicsから選ぶ)。「紹介アイコン」フィールドは種類を「画像」にしたpictというフィールドである。
このようにして、カテゴリーpatientsの記事を2つ作ってみた。
患者さん向け記事①
患者さん向け記事②
###ではコーディング
####各記事紹介ページを作成
まずはgatsby-config.js
にAPI、サービスID、エンドポイントを設定。
pagesの下にpatients.jsを作成、以下のようにコード。
// pages/patient.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
const PatientsPage = ({ data }) => (
<Layout>
<SEO title="患者の方へ" />
{data.allMicrocmsArticles.edges.map(edge => {
const articles = edge.node
const category = edge.node.category[0].name
console.log('◆categoryは ' + category)
if (category == 'patients') { //カテゴリーが患者さん用の場合表示
return (
<React.Fragment key={articles.id}>
<div>
<h2>{articles.title}</h2>
<p>{articles.feature}</p>
<img
src={articles.pict.url}
width={110}
height={110}
alt="pict画像"
/>
</div>
<div>
{articles.category.map(category => (
<React.Fragment key={category.id}>
<span>カテゴリー:{category.name}</span>
</React.Fragment>
))}
</div>
<hr />
</React.Fragment>
)
} else { return }
})}
</Layout>
)
export const query = graphql`
{
allMicrocmsArticles(
sort: { fields: [createdAt], order: DESC }
) {
edges {
node {
id
title
title_origin
category {
id
name
}
pict {
url
}
body
feature
}
}
}
}
`
export default PatientsPage
そして
gatsby develop
で立ち上げてhttps://localhost:8000/patients
にアクセスする。ふたつの記事のタイトルと紹介文と紹介画像が降順で表示されている。
GraphQLというのはよくわからんがこんな書き方をするのだなあ、と。
// pages/patients.js
・・・略・・・
export const query = graphql`
{
allMicrocmsArticles(
sort: { fields: [createdAt], order: DESC }
) {
edges {
node {
id
title
title_origin
category {
id
name
}
pict {
url
}
body
feature
}
}
}
}
`
・・・略・・・
http://localhost:8000/___graphql
にアクセスしてみる。するとGraphQLで受け取ってるデータとデータ構造が見れる。
allMicrocmsArticlesのedgesのnodeに記事のすべてが詰まってる。
GraphQLでうけとったデータをmapで回してじゅんぐりに表示、ということである。
個別記事の全表示ページを作成
動的なページを作成する際にはデフォではカラだったgatsby-node.jsファイルにコードする(えっ?)。そういうキマリ。
// gatsby-node.js
const path = require("path")
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(
`
{
allMicrocmsArticles {
edges {
node {
id
title
title_origin
category {
id
name
}
body
feature
pict {
url
}
}
}
}
}
`
)
if (result.errors) {
throw result.errors
}
result.data.allMicrocmsArticles.edges.forEach(edge => {
//上記のGraphQLでcategoryを書いてないがnode.categoryを掴めるようだ
const categoryName = edge.node.category[0].name
switch (categoryName) {
case 'patients': // categoryがpatientsだったらサブパスをpatientsに
subDir = '/patients/'+ edge.node.id
break;
case 'doctors': // categoryがdoctorsだったらサブパスをdoctorsに
subDir = '/doctors/'+edge.node.id
break;
default:
subDir = '/articles/'+edge.node.id
}
createPage({
//path: `/patients/${edge.node.id}`,
path: `${subDir}`,
component: path.resolve(
"./src/templates/article.js"
),
context: {
id: edge.node.id,
},
})
})
}
動的なページを作成するためにGatsbyにはcreatePagesというAPIが用意されてて、上のコードで肝になるのはそのcreatePages関数の中だけ。わたしは患者向け記事と医師向け記事と…でサブパスを分けたかったのでSwitch文があるが、単純に以下のようにシンプルでよい。
result.data.allMicrocmsArticles.edges.forEach(edge => {
createPage({
path: `/articles/${edge.node.id}`,
component: path.resolve(
"./src/templates/article.js"
),
context: {
id: edge.node.id,
},
})
})
component: path.resolve( "./src/templates/article.js" )
ではテンプレートビューファイルであるarticle.jsを指定してる。次のステップで作成する。
作成先がtemplatesフォルダになるのはそういうキマリかもしくは慣習。
context: { id: edge.node.id, }
では記事データのIDを指定している。こう書くだけで次のステップで作成するテンプレートに値渡しできるようである。
ではtemplatesフォルダを作成。
そしてその下にarticle.jsファイルを作成(ファイル名は任意)。
//templates/article.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
const ArticlePost = props => {
const post = props.data.microcmsArticles // ㊟allMicrocmsArticleでない
return (
<Layout>
<div>
<h2>{post.title}</h2>
<h3>原文:{post.title_origin}</h3>
<br />
<img
src={post.pict.url}
width={160}
height={110}
alt="pict画像"
/>
<p
dangerouslySetInnerHTML={{
__html: `${post.body}`,
}}
></p>
</div>
</Layout>
)
}
export default ArticlePost
export const query = graphql`
query($id: String!) {
microcmsArticles(id: { eq: $id }) {
title
title_origin
body
pict {
url
}
body
}
}
`
34行目のmicrocmsArticles(id: { eq: $id })
で、gatsby-node.jsのcontextで指定した記事IDが値渡しされている。そしてそのIDをもとにmicrocmsArticlesからデータをGraphQLで引っ張っている。個別の記事をとってきたいのでallMicrocmsArticleではないところ、注意。
さいごにpatients.jsにリンクをはる。
// pages/patients.js
・・・略・・・
<React.Fragment key={articles.id}>
<div>
<Link to={`/patients/${articles.id}`}>
<h2>{articles.title}</h2>
</Link>
<p>{articles.feature}</p>
・・・略・・・
これでgatsby developでビルドしなおすと(gatsby-node.jsファイルのコードを変更すると、変更内容にもよるがビルドしなおさないといけないみたい)詳細ページが表示されるようになる。
URLはコレ
titleをURLにしたかったらedge.node.titleにすれば以下のようになるだろう。日本語がイヤだったら記事コンテンツAPIに英語タイトルなりのフィールドを追加するだけだ(半角スペースはいれないよう)
http://localhost:8000/patients/患者さん用記事②
リロードしても404エラーにならない。すばらしい。
### 補足 医師向け記事も同じようにしてふたつ作った。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/3c5211a3-8f00-d40c-f582-f06a281fd8df.png)
pagesフォルダの下にdoctors.jsファイルを作成、patients.jsのコードをコピペして少し編集しただけ。microCMS側では記事を作成時、カテゴリーをdoctorsにするだけだ。
もちろん、gatsby-node.js
とtemplates/article.js
はなにも変更する必要ない。
// pages/doctors.js
import React from "react"
import { graphql, Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
const PatientsPage = ({ data }) => (
<Layout>
<SEO title="医師の方へ" />
{data.allMicrocmsArticles.edges.map(edge => {
const articles = edge.node
const category = edge.node.category[0].name
console.log('◆categoryは ' + category)
console.log('◆articles.idは ' + articles.id)
console.log('◆リンク先は ' + `/doctors/${articles.id}`)
if (category === 'doctors') { //カテゴリーが医師用の場合表示
return (
<React.Fragment key={articles.id}>
<div>
<Link to={`/doctors/${articles.id}`}>
<h2>{articles.title}</h2>
</Link>
<p>{articles.feature}</p>
<img
src={articles.pict.url}
width={110}
height={110}
alt="pict画像"
/>
</div>
<div>
{articles.category.map(category => (
<React.Fragment key={category.id}>
<span>カテゴリー:{category.name}</span>
</React.Fragment>
))}
</div>
<hr />
</React.Fragment>
)
}
})}
</Layout>
)
export const query = graphql`
{
allMicrocmsArticles(
sort: { fields: [createdAt], order: DESC }
) {
edges {
node {
id
title
title_origin
category {
id
name
}
pict {
url
}
body
feature
}
}
}
}
`
export default PatientsPage
補足2
React Bootstrapとの相性もすばらしい(Reactだからアタリマエか)。参考:GatsbyにReact bootstrap導入とナビゲーションバー
補足3
GraphQLも扱いが簡素で良い。JSONデータを読んでくるてのをやったがスムーズ、簡単。RESTより確かにいいかもしれない。Queryしか試してないけど…。
参考:
10分で GraphQL 入門
GraphQL解説 (AWS AppSync)
ギャツビー最高
確かにこれでイケるかもしれない。
海外では静的サイトジェネレータならGatsbyって流れになってるようだけど、日本で知名度がイマイチな理由は資生堂ギャツビーと同じ名前が微妙だからではないだろうか?
本の宣伝
Gatsbyバージョン5>>>>改訂2版
前編の『Gatsby5前編ー最新Gatsbyでつくるコーポレートサイト』と後編の『Gatsby5後編ー最新GatsbyとmicroCMSでつくるコーポレートサイト《サイト内検索機能付き》』を合わせ、次のようなデモサイトを構築します。
→ https://yah-space.work
静的サイトジェネレーターGatsby最新バージョン5の基本とFile System Route APIを使用して動的にページを生成する方法を解説。またバージョン5の新機能《Slicy API》《Script API》《Head API》を紹介、実装方法も。《Gatsby Functions》での問い合わせフォーム実装やGatsby Cloudへのアップロード方法も!
Gatsby5前編ー最新Gatsbyでつくるコーポレートサイト ~基礎の基礎から応用、新機能の導入まで(書籍2,980円)
最新Gatsby5とmicroCMSを組み合わせてのコーポレートサイト作成手順を解説。《サイト内検索機能》をGatsbyバージョン4からの新機能《Gatsby Functions》と《microCMSのqパラメータ》で実装。また、SEOコンポーネントをカスタマイズしてmicroCMS APIをツイッターカードに表示させるOGPタグ実装方法も解説。
Gatsby5後編ー最新GatsbyとmicroCMSでつくるコーポレートサイト《サイト内検索機能付き》(書籍 2,790円)