Table of Contents
はじめに
株式会社FundastAの片田です!
業務ではサーバーサイドを担当しておりますが、モダンフロントエンドにも興味があります。
そんな折、ちょうど良いところにブログを始めたい友人がおりましたので、NuxtとContentfulでナウいブログを構築してみました!
実際に作成したブログは下記URLからご覧いただけます。
https://vigilant-lichterman-42a0e2.netlify.com/
本記事では主にContentfulAPIを使ったブログ構築を私なりに噛み砕いて紹介していきます。
技術選定について
なぜNuxt.jsなのか?
- 勉強中のNuxt.jsでアウトプットしたかった。
 - Vueより簡単。
 - 初期表示速度も欲しかったので、SSRなブログを作ってみたかった。
 
SSRとは?
みなさんご存知かと思いますが、SSRって何?ってところを深堀しておきます。 こちらの記事を主に参考にさせていただきました。
私なりに解釈すると、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サイトで多くの方が解説されているので、詳細は割愛します。 簡単な流れとしては、
- Nuxtアプリケーションにnpmを使ってContentfulをインストールする
 - pluginsディレクトリにcontentful.js等の名前で設定ファイルを作成
 - nuxt.config.jsとかに設定を反映したりなんやらする
 - あとはビューでAPI叩くだけ!
 
詳しくはこちらの記事を参考にさせていただきました。
記事データの取得について
記事データを取得しているソースコードはこちらです!
| 
					 1 2 3 4 5 6 7 8 9 10 11 12  | 
						<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で定義している
| 
					 1  | 
						const client = contentful.createClient(config)  | 
					
を呼び出しています。
.getEntriesでは取得してくる記事のフィルタリングを行っています。
今回は記事一覧なので、cntentfulの、content modelをblogPost(任意の名前)に指定して、ブログ記事のみ取得しています。
.thenで実際に取得してきたデータをposts変数に詰めて返します。
contentfulAPIのデータはJsonで帰ってくるので、後々扱いやすい様に取得する値を絞っています。
エラーをハンドリングした際はconsole.logで出力します。
あとはビュー側で取得してきたpostsのデータを表示するだけ!
| 
					 1 2 3 4 5  | 
						<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をどのように作成するかによってデータは異なりますが、私の場合は、
| 
					 1 2 3 4 5  | 
						<template>   <ul>     <li v-for="(post, i) in posts" :key="i">{{ post.fields.tag.fields.name }}<li>   </ul> </template>  | 
					
で取得しています。
そしてタグのデータのみを全件取得する方法ですが、 これも前述した記事を全件取得するコードの、content modelを指定している箇所をtag用のcontent modelを指定する様に変更するだけです。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12  | 
						<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変数に格納すれば完成です。
ビューでの表示は、記事と同じ様に、
| 
					 1 2 3 4 5  | 
						<template>   <ul>     <li v-for="(tag, i) in tags" :key="i">{{ tag.fields.name }}</li>   </ul> </template>  | 
					
で表示されます!
おわりに
Nuxt.jsのアウトプットもできたし、それなりにかっこいいブログも作れたし(自己満足)、やってよかったです。
弊社の当ブログはVuePressというVue製の静的サイトジェネレータを使用して作成したので、後日記事にまとめてみます!
                
