公開日:7/5/2020  更新日:6/25/2021

  • twitter
  • facebook
  • line

Nuxt.js , microCMS ,Netlify の組み合わせでJAMstackなブログ開発

本ブログの作成方法、仕組みについて詳しく解説紹介します。Nuxt.js で技術ブログを作ってみたいけど、具体的にどうやって始めたらよいのか分からない人の助けになれたら幸いです。

目次

  1. 使用技術
  2. JAMstack
  3. システム体系
  4. 技術ブログの作成手順
    1. microCMS にコンテンツモデルの作成
    2. Nuxt.jsのプロジェクトの準備
    3. ホーム画面の作成 (記事の一覧表示ページ)
    4. 記事詳細ページの作成
    5. シンタックスハイライトの実装
    6. GitHub にNuxt プロジェクトを git push
    7. Netlify でホスティング
    8. microCMSに webhook、NetlifyにBuild hooksを設定
  5. エンハンス開発 備忘録
    1. ナビゲーションウィンドウを作成
    2. 独自ドメイン取得
    3. SNSシェアボタンを配置
    4. お問い合わせページを配置
    5. Google Analytics の設定
    6. サイトマップの設定
    7. metaタグの設定
  6. 参考サイトまとめ

使用技術

使用技術 概要
Nuxt.js Vue.js に基づいたプログレッシブフレームワーク。ブログサイト等を簡単に作れる。
microCMS APIで記事をJSON形式で取得できる日本製のHeadlessCMS。
Netlify 静的なサイトのホスティングサービスで、ビルドからデプロイ、ホスティングなどを全て賄ってくれる。

JAMstack

JAMstack とは、javascript, API, Markup の頭文字をとった造語で、これらの組み合わせで構成されるアーキテクチャの総称です。javascript がクライアントサイドを担当し、APIサーバとデータのやりとりをします。マークアップはジェネレーター等により静的な資材として吐き出されたテンプレートを指します。

システム体系

  • Nuxt.jsでブログサイトを構築しています。
  • 記事タイトルや記事本文はmicroCMSの管理画面で用意します。
  • microCMS から記事のJSON形式のデータを ayancDataメソッドで受け取り、記事を一覧表示します。動的ルーティングによりリンク先は自動生成しています。
  • Githabのリポジトリにソースをpushして、Netlifyのサービスにブログをデプロイします。
  • Netlifyは静的ジェネレイト (npm run generate) を実施して、distファルダにできた静的ファイルをホスティングしてくれます。
  • Githabで管理しているプロジェクトに変更 (commit) があると、Netlifyが自動でビルド反映してくれます。

技術ブログの作成手順

上記技術を用いて、JAMstackなブログ開発をする手順を具体的に示します。
本記事の手順を真似れば、本ブログのようなサイトが出来上がります (完成度低いですが) 。

1. microCMS にコンテンツモデルの作成

microCMS とは、登場してまだ日が浅い日本製HeadlessCMSサービスです。記事は管理画面から管理作成でき、記事ごとに生成されたAPIを叩くことで、JSON形式の記事データを取得することが出来ます。microCMS は日本製なので公式HPが日本語で理解しやすく、ブログ作成に必要な機能も充実しています。
まず最初は、microCMS に新規アカウント登録します。 こちら(microCMSのはじめ方) の本家記事にmicroCMSの始め方について説明があるので、詳しく知りたい方は参照して下さい。
今回は趣味の範囲でのブログ作成なので、無料枠で登録します。本ブログも無料枠を使用しています。

サービス名とサービスIDを決めてサービス登録が済んだら、次にリスト形式のAPIの作成にとりかかります。
以下のようにAPIスキーマで管理する各フィールドを作成して下さい。

必要最低限なフィールドとして、記事タイトルと記事コンテンツを用意しています。後々開発を進めていく中で、記事タイトル画像やカテゴリなどのフィールドを必要に応じて適宜追加していって下さい。今回は下記のように、テスト用にブログ記事を簡略に3つ用意しました。

microCMSの管理画面の右上にあるAPIプレビューで、さきほど作成した記事を取得する API リファレンスが参照できます。X-API-KEYをヘッダーに追記し、GETリクエストを送ると記事に関するJSONデータが返却されていることが分かると思います。

2. Nuxt.jsのプロジェクトの準備

まずは、node.jsをインストールして下さい。
Windowsの人はここからインストール

npm --version

上記コマンドでバージョンが表示されたらオーケーです。私は ver 6.14.4 をインストールしてます。
次に、プロジェクト用のフォルダを用意してからNuxtのプロジェクトを作成します。

mkdir test-blog
cd test-blog
npm install -g @vue/cli
npx create-nuxt-app

質問に答えて下さい。

create-nuxt-app v3.4.0
✨  Generating Nuxt.js project in .
? Project name: test-blog
? Programming language: JavaScript
? Package manager: Npm
? UI framework: Bootstrap Vue
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/JAMStack hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? What is your GitHub username? xxxx
? Version control system: Git

さっそく、サーバを立ち上げてみましょう。

npm run dev

http://localhost:3000/ に無事アクセスできたらオーケー。

3. ホーム画面の作成 (記事の一覧表示ページ)

さっそくコーディングしていきましょう。 まず、APIでmicroCMSとやり取りする際に必要となるAPIキーを .envファイルから環境変数として取得する処理を書いていきます。セキュリティの観点からAPIキーをコードにベタ書きしない方針ですね。dotenv のモジュールを使用するので、以下の npm コマンドでモジュールをインストールします。PromiseベースのHTTPクライアントaxiosも後に必要になるので、一緒にインストールしましょう。

npm install --save @nuxtjs/dotenv 
npm install --save axios

./test-blog/.env を新規作成します。.envファイルに、microCMSの管理画面から確認できる自分のAPI_KEYを設定して下さい。

//.env
API_KEY=××××××××××××××××××

nuxt.config.jsに環境変数と axios を使用するために以下を追記します。

//追記
require("dotenv").config();
const { API_KEY } = process.env;
const axios = require("axios");
----------------------------------------------------
//追記
env: {
  API_KEY
},

次に ./test-blog/index.vue を修正します。以下のように、index.vue を丸々書き換えて下さい。URL のxxxxの部分はご自身が登録したmicroCMSの設定値に変更して下さい。asyncDataメソッドにより記事一覧のJSONをmicroCMSより取得、v-for ディレクティブにより展開しています。

<template>
  <div>
    <h1>test-blog</h1>
    <div v-for="(item,key) in items" :key="key">
       <h2>{{ item.title }}</h2>
    </div>
  </div>
</template>
<script>
import axios from "axios";
export default {
  data() {
    return {
      items: []
    };
  },
  async asyncData() {
    const { data } = await axios.get(
      "https://xxxxx.microcms.io/api/v1/article",
      {
        headers: { "X-API-KEY": process.env.API_KEY }
      }
    );
    return {
      items: data.contents
    };
  }
}
</script>

<style>
 h1 {
    display: block;
    font-size: 3em;
    text-align: center;
    font-weight: bold;
    border-top: solid 3px #364e96;
    border-bottom: solid 3px #364e96;
  }
  h2 {
    display: block;
    font-size: 1.6em;
    text-align: center;
    font-weight: bold;
    border: solid #ddd;
    border-width: 0 0 1px 0;
  }
</style>

上手くいくと、下記のようにブログタイトルと記事見出しの一覧が表示されます。

4. 記事詳細ページの作成

管理画面にて記事をhtml形式やマークダウン形式で公開した場合、素のままだとhtmlタグがそのまま出力されます。 なので、@nuxtjs/markdownit を導入してマークダウン形式で記事を管理・表示できるようにします。

npm install --save @nuxtjs/markdownit

次に、markdownit を導入するために nuxt.config.js に以下の設定を追記します。

 //modulesに追記
 modules: ['@nuxtjs/markdownit'],

 //追加
 markdownit: {
  html: true,
  injected: true,
  preset: 'default',
 },

./test-blog/pages/article/_id.vue を新規作成して下さい。URL のxxxxの部分はご自身が登録したmicroCMSの設定値に変更して下さい。

<template>
  <div>
    <h1>{{ item.title }}</h1>
    <div v-html="$md.render(item.content)"></div>
    <nuxt-link :to="'/'">
        <h2>戻る</h2>
    </nuxt-link>
  </div>
</template>
<script>
import axios from "axios";

export default {
  data() {
    return {
      items: []
    };
  },
  async asyncData({ params }) {
    const { data } = await axios.get(
      `https://xxxxx.microcms.io/api/v1/article/${params.id}`,
      {
        headers: { "X-API-KEY": process.env.API_KEY }
      }
    );
    return {
      item: data
    };
  }
};
</script>
<style>
 h1 {
    display: block;
    font-size: 3em;
    text-align: center;
    font-weight: bold;
    border-top: solid 3px #364e96;
    border-bottom: solid 3px #364e96;
  }
</style>

記事一覧ページ (http://localhost:3000/) からリンクで記事詳細ページ (http://localhost:3000/article/xxxxx) に飛べるように、index.jsに nuxt-link を追加します。

//index.js
<template>
 <div>
  <h1>test-blog</h1>
  <div v-for="(item,key) in items" :key="key">
    <nuxt-link :to="'article/' + item.id">
       <h2>{{ item.title }}</h2>
    </nuxt-link>
  </div>
 </div>
</template>

上手くいくと、以下のように記事詳細ページが表示されます。

5. シンタックスハイライトの実装

技術ブログたるもの、コードにはシンタックスハイライトが適用されたいものです。本ブログでは、markdownitprismjs.js を使用してシンタックスハイライトと行番号を表示させていきます。まずは、prism.js をインストールします。

npm install prismjs

pluginsフォルダに ./test-blog/plugins/prism.js を新たに作成します。好きなcssテーマや、使用したい言語は各自で選んでインポートして下さい。ちなみに ./test-blog/node_modeles/prismjs/themes、./test-blog/node_modeles/prismjs/components 配下にインポート対象のファイルがあります。

//prism.js 
import Prism from 'prismjs'
//好きなcssのテーマを選ぶ、私のサイトは以下のcssテーマを使用
import 'prismjs/themes/prism-okaidia.css' 
 //使用したい言語を適宜追加 *デフォルトではjsやcssしか使えない
import 'prismjs/components/prism-***'
import 'prismjs/plugins/line-numbers/prism-line-numbers.min.js'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'

export default Prism

nuxt.config.js のplugins に prism を追加します。

plugins: ['~/plugins/prism'],

シンタックスハイライトを有効にしたい pages でprismを読み込みます。今回は記事詳細ページを有効にしたいので、_id.vue ファイルを以下のように修正します。

//_id.vue
...
import Prism from '~/plugins/prism'
export default {
...
  mounted() {
    Prism.highlightAll()
  },
...
}

行番号を付けるために、line-numbers のclass属性を付与。

//_id.vue
<div class="line-numbers" v-html="$md.render(item.content)"></div>

これでシンタックスハイライトと、コードブロックに行番号が出現しました。

6. GitHub にNuxt プロジェクトを git push

GitHub のリポジトリへ test-blog のソースコードをpushします。GitHubアカウントを持っていない人はアカウントを作成して下さい。新規作成したリモートリポジトリ (test-blog) にソースコードを push します。これでリモートリポジトリにソースコードをアップロードできました。

cd test-blog
git init
git add *
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/ユーザー名/test-blog.git
git push -u origin main

7. Netlify でホスティング

Netlify とは静的ホスティングサービスです。npm run generate コマンドを実施して、./test-blog/dist フォルダ配下に吐き出された静的ファイルをホスティングしてくれます。なので、静的ジェネレイトを実行するための動的パス設定を nuxt.config.js に追記する必要があります。

  generate: {
    routes() {
      const blog = axios
        .get("https://myfirstblog.microcms.io/api/v1/article", {
          headers: { "X-API-KEY": process.env.API_KEY }
        })
        .then(res => {
          return res.data.contents.map(blog => {
            return "/article/" + blog.id;
          });
        });
      return Promise.all([blog]).then(values => {
        return values.join().split(",");
      });
    }
  },

package.json のscriptsタグに、"generate": "nuxt generate"が設定されていることを確認してください。以下のように設定されていればよいです。

"scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate"
  },

続いて、Netlifyで新規サイトを作り、GitHub連携をします。前提として、Netlifyにサインアップして、アカウントを作っておいてください。なお、サインアップする際は、GitHubアカウントで認証しておいたほうがスムーズです。「New site from Git」を押してリポジトリ選択画面に移動したのち、先ほどGithubにプッシュした名前 (test-blog) のリポジトリを選択してください。次にNetlifyへデプロイする設定を追加します。リポジトリ内でデプロイの対象となるブランチにはマスターを指定します。Build commnadには静的サイトとしてビルドするコマンド、とPublish directoryには出力されたフォルダを指定します。

Advanced build settingsからmicroCMSのAPIキーをValueに設定します。

「Deploy site」のボタンを押してエラーが出なければ無事デプロイ成功です。発行されたurl (https://xxxxxx.netlify.com) にアクセスすると、デプロイされたサイトが表示されるはずです。

8. microCMSに webhook、NetlifyにBuild hooksを設定

microCMSの管理画面上で webhook、Netlifyでは Build hooksの設定をします。そうすることで,NetlifyがmicroCMSのAPI変更をトリガーに自動ビルドしてくれるようになります。つまり、microCMSの管理画面で記事を編集するだけで、公開されたサイトが自動で最新化されるわけです。いちいち、Git Push しなくて本番反映できるのは便利ですね。

まず Netlifyの設定画面にてSave ボタンを押下し,通知用のURLをメモします。

microCMSの管理画面にwebhookを設定します。先ほどメモしたURLを設定します。

エンハンス開発 備忘録

ここから先は、私が実際にブログをエンハンスしていった過程を簡単に備忘録として残したものです。

1. ナビゲーションウィンドウを作成

bootstrap-vueをインストールして,ナビゲーションウィンドウを作成。headerコンポーネントを各ページに配置。
header.vue コンポーネントを下記のように作成。pages配下にリンク先のページを適宜追加。

<template>
  <div class="title">
    <div>
      <b-navbar toggleable="lg" type="dark" variant="info">
        <b-navbar-brand>テストブログ</b-navbar-brand>
        <b-navbar-toggle target="nav-collapse" right></b-navbar-toggle>
        <b-collapse id="nav-collapse" is-nav right>
          <b-navbar-nav>
            <b-nav-item href="/">ホーム</b-nav-item>
          </b-navbar-nav>
          <b-navbar-nav>
            <b-nav-item href="/myself">自己紹介</b-nav-item>
          </b-navbar-nav>
        </b-collapse>
      </b-navbar>
    </div>
  </div>
</template>
<script>
export default {
}
</script>

2. 独自ドメイン取得

お名前ドットコムで独自ドメインを取得して設定。

3. SNSシェアボタンを配置

sns.vue コンポーネントを新規作成。

<template>
  <div>
    <ul class="sns">
      <li>
        <a :href="twitterURL" target="_blank" rel="nofollow">
          <img
            alt="twitter"
            src="~assets/images/twitter.svg"
            :width="size"
            :height="size"
          />
        </a>
      </li>
      <li>
        <a :href="facebookURL" target="_blank" rel="nofollow">
          <img
            alt="facebook"
            src="~assets/images/facebook.svg"
            :width="size"
            :height="size"
          />
        </a>
      </li>
      <li>
        <a :href="lineURL" target="_blank" rel="nofollow">
          <img
            alt="line"
            src="~assets/images/line.svg"
            :width="size"
            :height="size"
          />
        </a>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: '',
      required: true
    }
  },
  computed: {
    size() {
      return 36
    },
    url() {
      return `https://nuxtblog.work${this.$route.path}`
    },
    fixedTitle() {
      return encodeURIComponent(this.title)
    },
    fixedContent() {
      return encodeURIComponent(`${this.title} ${this.url}`)
    },
    twitterURL() {
      return `https://twitter.com/intent/tweet?url=${this.url}&text=${
        this.fixedTitle
      }`
    },
    facebookURL() {
      return `https://www.facebook.com/sharer/sharer.php?u=${this.url}&t=${
        this.fixedTitle
      }`
    },
    lineURL() {
      return `http://line.me/R/msg/text/?${this.fixedContent}`
    }
  }
}
</script>
<style scoped>
ul.sns {
  display: flex;
  flex-wrap: wrap;
}

ul.sns li {
  list-style-type: none;
  padding: 1.5em 1.0em 0 0;
}
</style>

4. お問い合わせページを配置

問い合わせページに Google フォームのHTMLコードを埋め込んで実装。こちらの記事 (GoogleフォームをWEBサイトに埋め込む方法)が参考になった。

5. Google Analytics の設定

モジュールをインポートする。

npm install --save @nuxtjs/google-analytics

nuxt.config.js に以下の設定を追記。xxxxxxxx に Google Analytics より取得したアナリティクスコード の id を設定する。

  modules: [
    ['@nuxtjs/google-analytics', {
      id: 'xxxxxxxx'
    }]
  ]

6. サイトマップの設定

モジュールをインポートする。

npm install --save @nuxtjs/sitemap

npm run generate を実行した際、動的ルーティングされたサイトマップ (sitemap.xml) がdistファルダに出力されるようにする。nuxt.config.js に以下の設定を追記する。

modules: [
    '@nuxtjs/sitemap',
],
sitemap: {
    path: '/sitemap.xml',
    hostname: 'https://xxxxx',
    routes (callback) {
      axios.get("https://xxxxx.microcms.io/api/v1/blog", {
          headers: { "X-API-KEY": process.env.API_KEY }
        })
      .then((res) => {
        var routes = res.data.contents.map((blog) => {
          return "/blog/" + blog.id
        })
        callback(null, routes)
      })
      .catch(callback)
    }

7. metaタグの設定

本ブログの別記事 (【Nuxt.js】動的に生成されたページに個別のmetaタグを設定する方法 )にて詳しく説明している。

8. ページング処理

こちらの記事 (NuxtのJamstack構成におけるページングの実装) を参考に index.vue, _id.vue, nuxt.config.js ファイルを修正。pager.vue コンポーネントを新たに作成、現在のページ番号が active化されるようにコーディング。

//pager.vue
<template>
  <div class="pager">
    <ul class="pagination">
        <nuxt-link :to="{ path: `/page/1`}">
            <li><div class = "listcss" v-bind:class="{ active: pageNum==1}"><span>1</span></div></li>
        </nuxt-link>
        <nuxt-link :to="{ path: `/page/2`}">
            <li><div class = "listcss" v-bind:class="{ active: pageNum==2}"><span>2</span></div></li>
        </nuxt-link>
        <!-- ページが増えた際に手動でliを追加する -->
    </ul>
  </div>
</template>
<script>
 export default {
    data() {
        return {
          //表示中のページ番号を取得する
          pageNum: this.$route.params.p || '1' 
        }
    }
 }
</script>
<style scoped>
//長いので省略
</style>

参考サイトまとめ

  1. Nuxt.jsとmicroCMSで採用ページを作成してみよう!
  2. Nuxt.js + Contentful + Prism
  3. Vue.js + Bootstrap4でポートフォリオサイトの雛形を作ろう!
  4. Navbar | Components | BootstrapVue
  5. Nuxt.js + Netlifyで爆速構築するサーバーレス開発入門
  6. nuxtでSNSボタンを自分で実装した
  7. GoogleフォームをWEBサイトに埋め込む方法
  8. (NuxtのJamstack構成におけるページングの実装)

戻る