microCMS

microCMS + NuxtでJamstackブログを作ってみよう

チュートリアル
2020/08/10 柴田 和祈

以前、チャリティーカンファレンス沖縄 2020 vol.1 フロントエンド編で行なったmicroCMSワークショップの内容を記事にしました。



このワークショップでは、microCMSとNuxt.jsを組み合わせJamstackなブログを作成することができます。
当時の内容はNuxt v2.13に沿ったものでしたが、本記事では内容をアップデートし、v2.14にて説明を進めます。

1. Nuxtプロジェクトを用意する

$ npx create-nuxt-app microcms-nuxt-jamstack-blog

ここでは設定項目は以下のようにします。

下記のコマンドで開発環境が立ち上がります。

$ cd microcms-nuxt-jamstack-blog
$ npm run dev

localhost:3000 にアクセスすると下記が表示されます。

2. microCMSの用意する

アカウント登録
ログイン
サービスの作成

サービスIDは一度設定すると変更ができないので、慎重に決めましょう。

APIの作成

いよいよBlog用のAPIを用意していきます。

リスト形式を選択します。

タイトル、本文のフィールドを用意します。

コンテンツの作成

適当に内容を入力し、公開します。
コンテンツ一覧画面に戻り、画面右上のAPIプレビューをクリックします。
取得ボタンをクリックし、入力内容がAPI経由で取得できるか確認してください(レスポンスJSONが表示されます)。

3. ブログ一覧を表示する

Nuxtでは pages/ 以下に作成したファイルに基づいて自動的にルーティングがされる仕組みになっています。

  • pages/index.vue → 記事一覧
  • pages/about.vue → Aboutページ
  • pages/_slug/index.vue → 記事詳細


記事詳細画面のように動的なページは _slugのようなディレクトリを間に挟む必要があります。(または _slug.vueでも良い)
URLからのパスに応じて slugという変数で値を受け取ることができます。

まずは一覧ページを用意していきます。
pages/index.vue を次のように変更してみましょう。

<template>
  <ul>
    <li v-for="content in contents" :key="content.id">
      <nuxt-link :to="`/${content.id}`">
        {{ content.title }}
      </nuxt-link>
    </li>
  </ul>
</template>

<script>
import axios from 'axios'
export default {
  async asyncData() {
    const { data } = await axios.get(
      // your-service-id部分は自分のサービスidに置き換えてください
      'https://your-service-id.microcms.io/api/v1/blog',
      {
        // your-api-key部分は自分のapi-keyに置き換えてください
        headers: { 'X-API-KEY': 'your-api-key' }
      }
    )
    return data
  }
}
</script>

microCMSのサービスid、api-keyを置き換えてください。
asyncData()というメソッドはサーバーサイドでもクライアントサイドでも動作可能です。
ここでAPI通信を行うことで、ビルド時の処理やページ遷移時の処理を共通化することができます。
参考:https://ja.nuxtjs.org/guide/async-data/

まず、axiosというHTTP通信用のライブラリをインストールします

$ npm install --save axios

次に、api-keyを設定するためにmicroCMSの管理画面に移動します。サービス設定 > API-KEYから確認ができます。

先ほどのソースコード内のX-API-KEYのところに値をセットします。
ここまで終えたところで、localhost:3000にアクセスすると記事一覧が表示されているはずです。

4. ブログ詳細を表示する

次はブログの記事詳細画面を作っていきます。
pages/ ディレクトリ以下に _slug/ ディレクトリを作成し、その中に index.vue を作成します

<template>
  <main class="main">
    <h1 class="title">{{ title }}</h1>
    <p class="publishedAt">{{ publishedAt }}</p>
    <div class="post" v-html="body"></div>
  </main>
</template>

<script>
import axios from 'axios'

export default {
  async asyncData({ params }) {
    const { data } = await axios.get(
      `https://your-service-id.microcms.io/api/v1/blog/${params.slug}`,
      {
        headers: { 'X-API-KEY': 'your-api-key' }
      }
    )
    return data
  }
}
</script>

asyncDataの引数のparamsの中にslugというプロパティが含まれており、こちらにURLからのパスが格納されてきます。
例えば、locahost:3000/fda49da2にアクセスした場合、slugfda49da2が格納されます。
この値を元にmicroCMSのブログAPIを呼び出し、該当の記事データを取得します。
localhost:3000にアクセスし、記事リンクをクリックすると詳細ページを表示することができます。

5. CSSで見た目を装飾する

microCMSのリッチエディタで記述した内容はHTML形式で取得することができます。
しかし、HTML内にclassを付与することが現状できないので、本文を囲うdivにclassを付与し、タグ指定でcssを書いていきます。
Scssで記述するために、node-sassとsass-loaderをインストールします。

$ npm install --save node-sass sass-loader

テンプレートファイルにstyleタグを追加し、CSSを書いていきます。
VueはHTMLとCSSそのものを変更している感覚でいじれるので、HTMLとCSSさえ分かっている人であれば雰囲気で書けると思います。

<template>
  <main class="main">
    <h1 class="title">{{ title }}</h1>
    <p class="publishedAt">{{ publishedAt }}</p>
    <div class="post" v-html="body"></div>
  </main>
</template>

<script>
import axios from 'axios'

export default {
  async asyncData({ params }) {
    const { data } = await axios.get(
      `https://your-service-id.microcms.io/api/v1/blog/${params.slug}`,
      {
        headers: { 'X-API-KEY': 'your-api-key' }
      }
    )
    return data
  }
}
</script>

<style lang="scss" scoped>
.main {
  width: 960px;
  margin: 0 auto;
}

.title {
  margin-bottom: 20px;
}

.publishedAt {
  margin-bottom: 40px;
}

.post {
  & > h1 {
    font-size: 30px;
    font-weight: bold;
    margin: 40px 0 20px;
    background-color: #eee;
    padding: 10px 20px;
    border-radius: 5px;
  }

  & > h2 {
    font-size: 24px;
    font-weight: bold;
    margin: 40px 0 16px;
    border-bottom: 1px solid #ddd;
  }

  & > p {
    line-height: 1.8;
    letter-spacing: 0.2px;
  }

  & > ol {
    list-style-type: decimal;
    list-style-position: inside;
  }
}
</style>


6. ビルドして静的ファイルを生成してみる

今まではnpm run devで開発していましたが、これはいわゆる開発モードで、デプロイする際はビルドして静的ファイルの形で配置します(Jamstackなので)。
下記のコマンドを叩いて、手元で一旦ビルドしてみましょう。

$ npm run generate


デフォルトでは静的ルーティングパスしか生成されません。
/_slug/ のような動的なルーティングには別で設定が必要となります。
nuxt.config.jsを編集し、generate項目を付け足します。
ここでは、SSG(スタティックサイトジェネレート)時にどんなパスでどんなファイルを生成するかを指定しています。
axiosのimportを忘れずに!

import axios from 'axios'

export defualt {
  // 略
  generate: {
    async routes() {
      const pages = await axios
        .get('https://your-service-id.microcms.io/api/v1/blog?limit=100', {
          headers: { 'X-API-KEY': 'your-api-key' }
        })
        .then((res) =>
          res.data.contents.map((content) => ({
            route: `/${content.id}`,
            payload: content
          }))
        )
      return pages
    }
  }
}

もう一度 npm run generate を行うと、各ページが生成されます。

下記のコマンドを叩くことで、dist/ 配下に生成されたHTMLをlocalhost上で閲覧できるので、正しくビルドできていることが確かめられます。

$ npm start


7. ファイルをホスティングする

ブログの機能としてはまだまだですが、一旦ホスティングまでやってしまいましょう。
ホスティング先として今回はNetlifyを利用します。
Netlifyを利用するためにはGitHub連携が必要なので、今までの作業内容をGitHubにpushしましょう。

まず、GitHubでリポジトリを作成します。

PUSHします。

$ git init
$ git add .
$ git commit -m 'first commit'
$ git remote add origin your-repository  // 自分のリポジトリを入力
$ git push -u origin master

Netlifyにログインします。(未登録の方はSignupお願いします)
new site from git ボタンからサイトを新規作成します。

ビルドコマンド、デプロイ先は下記のように設定します。

以上でNetlifyとGitHubが連携してビルドが開始されます。
ビルドが完了したら、Netlifyにホスティングされます。

8. microCMSとNetlifyを連携する

次は、microCMSのコンテンツを変更したらNetlifyのビルドが走るようにします。
API設定 > Webhook からNetlifyを選択します。

NetlifyのWebhookを用意します。
Netlify側のSettings > Build & deploy > Build hooksから設定可能です。

作成するとエンドポイントが割り当てられます。

これをmicroCMS側のWebhook設定に入力し保存します。

以上で連携完了になります。
microCMS側でコンテンツを作成して、Netlifyに反映されるか試してみましょう。
反映されればJamstack構成の完成です!

9. カテゴリーを追加する

おまけにブログにカテゴリーをつけてみましょう。
カテゴリーをつけるにはコンテンツ参照機能を用います。
まずは新しくカテゴリーAPIを作成します。




次に、ブログの API設定 > APIスキーマ に新しくカテゴリーフィールドを追加します。
種類はコンテンツ参照で、カテゴリーAPIを指定します。

このように設定することで入稿時にカテゴリーが選択できるようになり、APIレスポンスにもデータが含まれた形でレスポンスされます。
詳細画面のテンプレートにカテゴリーを加えてみましょう。

<template>
  <main class="main">
    <h1 class="title">{{ title }}</h1>
    <p class="publishedAt">{{ publishedAt }}</p>
    <p class="category">{{ category && category.name }}</p>
    <div class="post" v-html="body"></div>
  </main>
</template>

実際にブラウザで確認し、カテゴリーが表示されればOKです。

おわりに

microCMSとNuxt.jsを組み合わせてJamstack構成のブログを作成しました。
無事、作成できましたでしょうか?

今後の躓きポイントとしては以下のようなものが挙げられます。


これらに関しては、別記事で解説していきたいと思います。

-----

microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitterメールからお気軽にご連絡ください!
引き続きmicroCMSをよろしくお願いいたします!

ABOUT ME

柴田 和祈
microCMSのデザイン、フロントエンド担当 / ex Yahoo / 2児の父 / 著書「React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで 」 / Jamstack

microCMSとは

  1. 開発者、編集者どちらも分かりやすい管理画面

  2. 細かな権限管理や豊富な外部サービス・データ連携

  3. 安心の日本製・日本語でのチャットサポート