Nuxt.js + Contentful + ElementUI + Netlifyでブログを構築してみた。

# はじめに

名古屋でバックエンドエンジニアとして駆け出した私です！
業務ではサーバーサイドを担当しておりますが、どちらかというとモダンフロントエンドに興味があります。
そんな折、ちょうど良いところにブログを始めたい友人がおりましたので、NuxtとContentfulでナウいブログを構築することにしました！

本記事では主にContentfulAPIを使ったブログ構築を私なりに噛み砕いて紹介していきます。

# 技術選定について

## なぜNuxt.jsなのか？

- 勉強中のNuxt.jsでアウトプットしたかった。
- Vueより簡単。
- 初期表示速度も欲しかったので、SSRなブログを作ってみたかった。

### SSRとは？

みなさんご存知かと思いますが、SSRって何？ってところを深堀しておきます。
[こちらの記事](https://inside.dmm.com/entry/2018/04/10/nuxt-firebase)を主に参考にさせていただきました｡

私なりに解釈すると､**SSRとは､本来クライアントがレンダリングする部分をサーバーでレンダリングしておき､クライアントに返すようにするもの**です｡
SSR(サーバーサイドレンダリング)の名前のとおりです笑
SSRアプリケーションにすることで､SPA(シングルページアプリケーション)のデメリットである､初期表示速度が遅いことや､SEO的に不利になる(クローラーがうまくクローリングしてくれない)ことを解消できます｡

(今はSPAでもSEO的に不利になることはない､という情報を目にしたことがありますが､ここでは言及しません)

## なぜContentfulなのか？

- これからWordPress独自の仕様や言語(PHP)を学ぶのは嫌だ｡ → CMS側の学習コストなどはとくにかからない｡
- 実際にブログを書くのは非エンジニアの友人なので、わかりやすいUIが整ってる方が良かった。
- ヘッドレスCMSって響きかっこいい。なんか使ってみたかった。
- フロント以外の全てのことをcontentfulで済ませることができるし、細かいところまで設定＆カスタマイズできるところが面白そう。

## ヘッドレスCMSとは？

そもそも､CMSとは何でしょう?
ブログを運営したことある方なら､真っ先にWordPressが頭に浮かびますよね｡
CMS(コンテンツマネジメントシステム)とは､Web制作の知識がなくても簡単にブログやWebサイトを構築､管理､更新できるシステムのことを言います｡

今回はただのCMSではなく､ヘッドレスCMSです｡
**ヘッドレスCMSは､ビュー(フロント)がないCMSのこと**だと認識しています｡
今回使用したContentfulも､記事の更新､管理は簡単にでき､管理画面は用意されているものの､実際にユーザーに表示される部分は用意されていません｡
その代わりに､APIとして記事の情報を取得することができたりするので､フロントエンドは自身で作り込むことができるのです｡

## なぜElementUIなのか？

- 手軽に整ったUIを試してみたかった。
- Vuetifyは使ったことあるので、使ったことないものを使ってみたかった。

## なぜNetlifyなのか？

- GitHubと連携して、ほぼ設定いらずで自動デプロイできるのが魅力的。（最高）
- 自動でセキュアなURLにしてくれるのも魅力的。
- しばらくは無料枠のまま使い続けられそうだったから。
- firebaseは使ったことあるから、別のもの使ってみたかった。
- なんか使ってみたかった。

# ContentfulAPIについて

## 今回実装したこと
- 記事データを全て取得して、記事一覧を表示する
- 記事データを全て取得して、記事内容を表示する
- 記事にタグを付けられる様にして、記事データと一緒にタグを取得、表示する
- タグデータを全て取得して、タグ一覧を表示する
- タグで記事を検索する
- 記事名のキーワードで記事を検索する

## NuxtアプリケーションとContentfulAPIの連携方法について

フロントとAPIの連携に関しては､他のQiita記事やWebサイトで多くの方が解説されているので､詳細は割愛します｡
簡単な流れとしては､
1. Nuxtアプリケーションにnpmを使ってContentfulをインストールする
2. pluginsディレクトリにcontentful.js等の名前で設定ファイルを作成
3. nuxt.config.jsとかに設定を反映したりなんやらする
4. あとはビューでAPI叩くだけ!

詳しくは[こちらの記事](https://qiita.com/isihigameKoudai/items/3e45ade7c438176a4cc9)を参考にさせていただきました｡

### 記事データの取得について

記事データを取得しているソースコードはこちらです！

```html
<script>
 asyncData({ env }) {
   return client
     .getEntries({ content_type: env.CTF_BLOG_POST_TYPE_ID })
     .then(entries => {
       return {
         posts: entries.items
       }
     })
     .catch(console.error)
 }
</script>
```

asyncDataを使って非同期でAPIと通信します。（引数に渡しているenvはcontentfulのapiKeyなどを隠してあるdotenvの内容です）
戻り値のclientですが、plugins/contentful.jsで定義している

```js
const client = contentful.createClient(config)
```

を呼び出しています。

.getEntriesでは取得してくる記事のフィルタリングを行っています。
今回は記事一覧なので、cntentfulの、content modelをblogPost(任意の名前)に指定して、ブログ記事のみ取得しています。

.thenで実際に取得してきたデータをposts変数に詰めて返します。
contentfulAPIのデータはJsonで帰ってくるので、後々扱いやすい様に取得する値を絞っています。
エラーをハンドリングした際はconsole.logで出力します。

あとはビュー側で取得してきたpostsのデータを表示するだけ！

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

ビューのソースコードは適当ですが、こんな感じでデータを表示することができます。

### 記事とタグの関連付けと、タグデータの取得について

contentfulで記事のタグ付けを行うには、contentfulの管理画面で、tag用のcontent modelを追加します。
管理画面がらいくつかタグを新規作成したら、
記事のcontent modelを編集　→　refarencesで先ほど作成したtag用のcontent modelを関連付け
これで記事にタグ付けができる様になります！

タグデータの取得は二通りあり、
ひとつは前項で取得した**記事データの中からタグのデータを抽出する方法**。
もうひとつは**タグのデータのみを全て取得する方法**です。

まずは記事データの中からタグのデータを抽出する方法についてですが、
これは先ほど取得したjsonデータの中にその記事に関連づけられたタグのデータも含まれていますので、
jsonをみながらビューで表示してやれば良いです。

content modelをどのように作成するかによってデータは異なりますが、私の場合は、

```vue

<template>
  <ul>
    <li v-for="(post, i) in posts" :key="i">{{ post.fields.tag.fields.name }}<li>
  </ul>
</template>
```

で取得しています。

そしてタグのデータのみを全件取得する方法ですが、
これも前述した記事を全件取得するコードの、content modelを指定している箇所をtag用のcontent modelを指定する様に変更するだけです。

```vue
<script>
 asyncData({ env }) {
   return client
     .getEntries({ content_type: env.CTF_TAG_TYPE_ID })
     .then(entries => {
       return {
         tags: entries.items
       }
     })
     .catch(console.error)
 }
</script>
```

具体的にいうと、getEntriesメソッドの引数に渡す値でフィルタリングできるので、そこを予め取得しておいたtag用のcontent modelのidに差し替えました。
こうすることでタグデータのみ全件取得することができるので、あとは取得したデータをtags変数に格納すれば完成です。

ビューでの表示は、記事と同じ様に、

```vue
<template>
  <ul>
    <li v-for="(tag, i) in tags" :key="i">{{ tag.fields.name }}</li>
  </ul>
</template>
```

で表示されます！

# おわりに

Nuxt.jsのアウトプットもできたし､それなりにかっこいいブログも作れたし(自己満足)､やってよかったです｡
次は自分で使うブログを､VuePressなんかを使って構築してみたいと目論んでいます｡