Gatsby + Contentful + Github pagesで綺麗なブログを作成してみる

# 目的

デザインテーマを適用したJAMstackなブログサイトをセットアップします。

# 用意するもの

- Contentfulのアカウント
- ブログの著者アイコンとして利用するアバター画像(顔写真など)
- GitとNodeと、npmかyarnがつかえる環境

# 作業環境

| 項目 | Version |
| --- | --- |
| Ubuntu | 18.04 |
| node | v14.7.0 |
| yarn | 1.21.1 |

# Gatsby+Themeのセットアップ

GatsbyはReact製の静的サイトジェネレータです。Webサーバで公開するためのhtmlファイルやcssファイルを作成してくれます。多くのテーマが公開されています。

## デザインテーマを決める

次のサイトなどでGatsby用でContentfulに対応しているテーマを探します。

- https://jamstackthemes.dev/
- https://themejam.gatsbyjs.org/showcase

今回は多くのGithubスターを集めている[gatsby-theme-novela](https://github.com/narative/gatsby-theme-novela)を利用します。
下のようなテーマです。

![novela.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51434/80b50051-a805-934f-63a0-7b3dd860d1c9.png)

[こちら](https://www.narative.co/labs/novela/)でLiveデモを確認できます。

## テーマを取得

ここでgatsby-theme-novelaをcloneしたいところですがREADMEを読むとgatsby-startarのためのリポジトリは別に存在します。なので次のリポジトリをcloneしてください。

[gatsby-starter-novela](https://github.com/narative/gatsby-starter-novela)

```shell
git clone git@github.com:narative/gatsby-starter-novela.git <ローカルフォルダ名>
```

## セットアップと確認用サーバ起動

READMEの通りにコマンドを実行します。

```shell=
cd <ローカルフォルダ名>
yarn
yarn global add gatsby
yarn dev
```

次のURLで表示されれば成功です。

http://localhost:8000/

# Contentful関連のセットアップ

記事データはContentfulというサービスに保存します。投稿や修正もContentfulの管理画面から実施します。

## Spaceを作成

SpaceはContentfulにおけるプロジェクトのような概念です。Webの管理画面から作成してください。

無料プランでは１つしか作成できないのですが、アカウント登録時にサンプルデータを作成していると既に１つ作られていて追加できませんので、サンプル用のSpaceを削除する必要があります。

## Contentfulにブログ用モデルを追加

READMEと順番が違いますが、先にContentfulへブログ用のモデルを追加します（モデルとはRDBにおけるTableのような概念です）。

モデルの構造はテーマによって違うので、他のテーマで作業する場合はREADMEを参照しながら適宜読み替えてください。

### Contentful CLIのインストール

モデルのインポートをWebコンソールから出来ると良いのですが、方法が分からないのでCLIをインストールしてコマンドラインから実施します。

```shell=
# yarnの場合
yarn global add contentful-cli

# npmの場合
npm -g contentful-cli
```

詳細は次サイトにあります

https://www.contentful.com/developers/docs/tutorials/cli/installation/

### テーマ用のモデル定義ファイルをダウンロード

次のURLにあるcontentful-export.jsonをダウンロードします。

https://github.com/narative/gatsby-theme-novela/tree/master/%40narative/gatsby-theme-novela/contentful

コピー＆ペーストでも良いですが、直接ダウンロードする場合は次のようにします。

```shell=
wget https://raw.githubusercontent.com/narative/gatsby-theme-novela/master/%40narative/gatsby-theme-novela/contentful/contentful-export.json
```

### モデルをインポート

```shell=
# Contentful cliの利用を開始する
# 対話式にキーをコピペしてログイン処理を実施
# (nodeのバージョン管理環境によっては、「npx contentful login」とする必要があるかもしれません）
contentful login

# 利用するspaceを選択
# 対話式にスペースを選択
contentful space use

# モデルのインポートを実施
contentful space import --content-file contentful-export.json
```

The import was successful. と表示されれば成功です。

上記インポートでは、著者情報と記事情報の二つのモデルが作成されます。

- Auther（著者情報）
- Post（記事情報）

## （テーマ固有のトラブル対応）

残念なことに、モデル作成用として配布されているjsonファイルの内容と、実際にテーマが使用しているモデルの名前が一致しません。バグなのか、更新のミスマッチなのかわかりませんが、次の作業が必要です（2020年7月30日現在）。

ややこしい話ですが、このトラブルはテーマのバージョンが0.16(付近)以降に発生しているようです。依存関係により0.13など古いバージョンがインストールされる場合があり、この場合は次のモデル名の修正は不要です。

モデル名の修正は、ContentfulのWebコンソールから、Postのモデルを「Duplicate」し、Articleとして複製して保存します。

これで、Contentfulには次の３つのモデルが作成された状態になります。

- Auther（著者情報）
- Post（記事情報）
- Article（記事情報）

古いPostモデルは削除しないでください。エラーが発生します。

## Contentfulへcontentを追加

AutherとArticleにcontent（RDBで言う所のレコード）を追加します。

Web画面で、Content -> Add entry の順にクリックして各モデルに対するcontentを作成します。今回はサンプルとして次の情報を入れました。

### Auther(著者情報)のサンプルcontent

![auther.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51434/4351cca2-499f-d01a-bb72-aa30e82fe146.png)

＊画像などのメディアが一つも登録されていないとGatsbyでデータを取得する際にエラーが発生する場合があるようです。著者アイコンはとりあいず入れておいた方がよさそうです。


### Article(記事情報)のサンプルcontent

(画像ではモデル名がPostとなっていますが、Articleと読み替えてください)

![post.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51434/d19d6a9e-7b61-1066-f9e7-87dee06e72c9.png)

どれも一般的な項目ですが、いわゆるアイキャッチ画像のフィールド名がHeroなのは最初戸惑いました。「Excerpt」はトップの一覧で使用される要約文で、Max200文字とありますが一定の文字数以降は「...」と省略されてしまうので注意が必要です。

## Contentfulとの接続設定

READMEに従って.envファイルとgatsby-config.jsを編集します。初めに、必要になるキー情報を取得します。

### Contentfulのキー情報を取得

Contentfulの管理画面へログインし、

「settings」ー＞「API Keys」と選択してKey情報の管理ページを開き、右上の「Add API Key」を押して今回利用するための鍵を作成します。

作成した鍵情報のうち、次の２つを使用します。

- Space ID
- Content Delivery API - access token

### .env を編集

.envファイルを作成もしくは開き、次の2行を追加します。

```shell=
CONTENTFUL_SPACE_ID= (Your Contentful Space ID)
CONTENTFUL_ACCESS_TOKEN= (Your Content Delivery API - access token)
```

各変数の右辺に、先ほど作成した２つの鍵情報をコピーして保存します。

### 必要なモジュールを追加

次のコマンドで追加します。

```shell
yarn add gatsby-source-contentful dotenv
```

### gatsby-config.js を編集

READMEのサンプルを元に、既存のgatsby-config.jsを編集します。

READMEにあるサンプルは次のとおりですが、これをそのままコピペしては***いけません***。

```
require('dotenv').config();

plugins: [
  {
    resolve: 'gatsby-source-contentful',
    options: {
      spaceId: process.env.CONTENTFUL_SPACE_ID,
      accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
    },
  },
  {
    resolve: '@narative/gatsby-theme-novela',
    options: {
      sources: {
        contentful: true,
      },
    },
  },
];
```

既存のgatsby-config.jsの構造を考えながら、次のように書き換えます。

```diff
+ require('dotenv').config();

module.exports = {
  siteMetadata: {
    title: `Novela by Narative`,
    name: `Narative`,
    siteUrl: `https://novela.narative.co`,
    description: `This is my description that will be used in the meta tags and important for search results`,
    hero: {
      heading: `Welcome to Novela, the simplest way to start publishing with Gatsby.`,
      maxWidth: 652,
    },
    social: [
      {
        name: `twitter`,
        url: `https://twitter.com/narative`,
      },
      {
        name: `github`,
        url: `https://github.com/narative`,
      },
      {
        name: `instagram`,
        url: `https://instagram.com/narative.co`,
      },
      {
        name: `linkedin`,
        url: `https://www.linkedin.com/company/narative/`,
      },
      {
        name: `dribbble`,
        url: `https://dribbble.com/narativestudio`,
      },
    ],
  },
  plugins: [
    {
      resolve: "@narative/gatsby-theme-novela",
      options: {
        contentPosts: "content/posts",
        contentAuthors: "content/authors",
        basePath: "/",
        authorsPage: true,
        sources: {
-          local: true,
+          local: false,
+          contentful: true,
        },
      },
    },
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `Novela by Narative`,
        short_name: `Novela`,
        start_url: `/`,
        background_color: `#fff`,
        theme_color: `#fff`,
        display: `standalone`,
        icon: `src/assets/favicon.png`,
      },
    },
-    {
-      resolve: `gatsby-plugin-netlify-cms`,
-      options: {
-      },
-    },
+    {
+      resolve: 'gatsby-source-contentful',
+      options: {
+        spaceId: process.env.CONTENTFUL_SPACE_ID,
+        accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
+      },
+    },
  ],
};
```

プラグインの部分の「+  local: false」はReadmeに無い項目ですが、これをしないとlocalの記事情報の読み込みがオフになりませんでした。バグかもしれません（2020年7月30日現在）。

### ローカルで改めて起動

```。
yarn dev
```

次のURLで、先ほどContentfulに登録したAuther情報とArticleの内容が表示されれば成功です。

http://localhost:8000

![local.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51434/e58cdbb3-579a-f46e-d45a-b0ae84e4202a.png)


# Github pagesへデプロイ

ひとまずGatsby+Contentfulでの環境構築が完了しました。gatsby buildと打てば./publicの下に静的ファイルが生成されるので、これをGithubのpages用ブランチにプッシュしてgithub pagesとして公開できますし、もちろん他のホスティングサービスを利用することもできます。

今回はGithub pagesを利用するための設定を追加します。

## gh-pagesの追加

node製のツールのgh-pagesを利用します。

Github pages用のブランチ作成や公開用ファイルだけをブランチとしてプッシュするなどの処理を自動化できて便利です。

### gh-pages のインストール

```shell=
yarn add gh-pages -D
```

### サイト構成の設定

Github pagesでサイトを公開する場合、つぎのようなURLになります。

https://<ユーザID>.github.io/<リポジトリ名>/

サブディレクトリ対応をせずにデプロイすると404エラーなどが発生するため、gatsby-config.jsに設定を入れます。

便宜上、次のURLを例に説明します。

https://userid.github.io/mypage/

編集するのは次の二ヶ所です。

1. ```module.exports = {```の直下に```pathPrefix```を追加します。
2. ```siteMetadata```内の```siteUrl```を変更します。

変更例

```diff
...
module.exports = {
+  pathPrefix: `/mypage/`,
  siteMetadata: {
    ...
-    siteUrl: `https://novela.narative.co`,
+    siteUrl: `https://userid.github.io`,
    ...
```

私自身はカスタムドメインで運用する予定のため、上記のサブディレクトリ構成はお試しで動作確認しただけです。一応404などのエラーは全て消えていましたがもし不都合など発生した場合はすみません。コメント頂けるとありがたいです。

### ビルドしてデプロイする

次の手順でビルド+デプロイします。

```shell=
# 念の為キャッシュをクリア
# npm cache clean
yarn cache clean

# ビルドを実施
gatsby build --prefix-paths

# gh-pagesを用いてデプロイ
# 環境によってはnpxが不要なケースもあると思います。
gh-pages -d public
```

Published　と表示されればデプロイ成功です。

Github PagesのURLにアクセスし、さきほどローカルで確認したものと同じページが表示されていれば成功です。

あとはgatsby-config.jsonなどの情報を自分用に書き換えて、JAMStackなブログ生活をお楽しみください。