【次世代のWordPress？】Nuxt.jsでヘッドレスCMS「contentful」を始めてみる

ブログを始めようとなると、まず思いつくのはWordPressですよね。

ほとんどコーディングをすることなくブログの開設ができて、いろんなツールもそろっているので文句のつけようがありません。

しかし、プログラマだったらもっと自由に拡張したり、好きな言語で開発のできるCMSを求めているのではないでしょうか。

そんな創作意欲あふれる方にオススメしたいのが、ヘッドレスCMSと言われるものです。

# ヘッドレスCMSとは

ヘッドレスCMSとは、簡単に説明するなら従来のCMSとは異なり、バックエンドのみに特化したCMSであり、RESTFulなAPIを経由して、様々なデバイスからアクセスできるようにしたものです。

従来のWordPressが
ブログ記事などのコンテンツをフロント側からAPI経由で呼び出すだけなので、フロント側は作り手が自由に構築することができます。

ヘッドレスCMSはコンテンツを保存、デリバリーすることに特化しているのです。
図に表してみるとこのようになります。

通常のCMS
![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265549/fa12cb79-c030-1f38-111e-ec6030db44b0.png)

ヘッドレスCMS

![Untitled Diagram (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265549/e36faff4-cd7b-5eb9-afac-ebf8aa06cf0b.png)



# ヘッドレスCMSのメリット・デメリット
ではヘッドレスAPIのメリットデメリットをまとめてみます。

・メリット
プラットフォームから独立している。
自由に言語やフレームワークを選ぶことができる
拡張が自由かつ無限大

・デメリット
従来のCMSに比べコーディング量が桁違いに多くなる
便利なプラグインなどが使えない。


# 実際にNuxt.jsでヘッドレスCMSを体験してみる
今回用いるヘッドレスCMSは「contentful」です。ヘッドレスCMSの中ではメジャーなもので、無料でブログに必要な基本的な機能がそろっているので、個人がとりあえずブログを始めてみるには十分なものとなっています。


今回は公式のチュートリアルを参考に、とりあえずブログコンテンツを画面に表示するところまでを紹介します。

※事前にこちらで登録を行ってください。
https://www.contentful.com/

では実際に開発を行っていきます。

## Nuxtアプリの作成
```bash
npm install -g vue-cli #vue-cliのインストール
vue init nuxt/starter my-blog #Nuxtアプリの作成
cd my-blog

```
# contentful-cliのインストール
```bash
npm i -g contentful-cli #contentful-cliのインストール
contentful login #ウェブブラウザが開くので、ログインをしてください
contentful space create --name 'my-blog' #データの保存先であるスペースを作ります。
contentful space use #上で作ったスペースを選択してください。
```
次にスペースにサンプルデータを入れていきます。下記のコマンドを打つだけで、一般的なブログに必要なDB構成とサンプルデータが作成されます。すごく簡単ですね。

```bash
contentful space seed --template blog 
```


また、APIトークンを取得する必要があります。Webブラウザ上でcontentfulにログインして、先ほど作ったスペースを選択します。

するとTopに「Fetch your content」というメニューが表示されているはずです。「Use the API」をクリックしてください。

そしてそこにある
・Space ID
・Content Delivery API - access token
の二つを忘れないように保存しておいてください。

# 実際にコードを書く

```bash
npm install --save contentful 
```

pluginディレクトリの配下にcontentful.jsを作成して以下のように記載してください。

```javascript:plugin/contentful.js
const contentful = require( 'contentful' )

const config = {
  space: process.env.CTF_SPACE_ID,
  accessToken: process.env.CTF_CDA_ACCESS_TOKEN
}

module.exports = {
  createClient() {
    return contentful.createClient( config )
  }
}

```
続いてはAPIトークンなどを書き込む設定ファイルを作成します。

```javascript:.contentful.json

{
  "CTF_PERSON_ID": "15jwOBqpxqSAOy2eOO4S0m",
  "CTF_BLOG_POST_TYPE_ID": "blogPost",
  "CTF_SPACE_ID": "先ほど取得したもの",
  "CTF_CDA_ACCESS_TOKEN": "先ほど取得したもの"
}

```

続いてnuxt.config.jsに以下のコードを追加します。

```javascript:nuxt.config.js
const config = require('./.contentful.json')

module.exports = {
  // ...
  env: {
    CTF_SPACE_ID: config.CTF_SPACE_ID,
    CTF_CDA_ACCESS_TOKEN: config.CTF_CDA_ACCESS_TOKEN,
    CTF_PERSON_ID: config.CTF_PERSON_ID,
    CTF_BLOG_POST_TYPE_ID: config.CTF_BLOG_POST_TYPE_ID
  }
  // ...
}

```

最後にindex.vueに以下を追加して、APIで取得したデータを画面上に表示させます。
※公式のものをそのままコピーするとエラーになるので注意してください。

```vue:index.vue
<template>
  <div>
    <h1>{{ person.fields.name }}</h1>
    <ul>
      <li v-for="(post, index) in posts" :key="index">{{ post.fields.title }}</li>
    </ul>
  </div>
</template>

<script>
import { createClient } from "~/plugins/contentful.js";

const client = createClient();

export default {
  asyncData({ env }) {
    return Promise.all([
      client.getEntries({
        "sys.id": env.CTF_PERSON_ID
      }),
      client.getEntries({
        content_type: env.CTF_BLOG_POST_TYPE_ID,
        order: "-sys.createdAt"
      })
    ])
      .then(([entries, posts]) => {
        return {
          person: entries.items[0],
          posts: posts.items
        };
      })
      .catch(console.error);
  }
};
</script>

```

ここまで記載したら以下でNuxtアプリをstartさせてください。

```bash
npm run dev
```

以上になります。
特にCSSなどは当ててないですが、以下のようにcontentful上に保存されているデータを表示することができたはずです。

<img width="589" alt="Screen Shot 2019-07-22 at 1.22.43 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265549/9ae05b67-2146-3a83-84c3-88d6c5a4abd2.png">

自分はこのcontentfulを利用して、three.jsを用いた3Dグラフィックのインターフェイスを持つブログ兼ポートフォリオサイトを作りたいと考えています。

# 参考資料
https://www.contentful.com/developers/docs/javascript/tutorials/integrate-contentful-with-vue-and-nuxt/
https://qiita.com/teradonburi/items/fd2c34a52c0c4cfd0d22