Nuxt.js + Contentful + Netlify で簡単なブログを作る


きっかけ

友人と共同編集できるブログを開設したくて、WordPressを使おうとしたのだけれど、CSSカスタマイズなどはビジネルプラン(月1000円!)に加入する必要があってWordPressに萎えてしまった。
noteはいいね機能がいらないし、TumblrはSNS味が強いし、、、てなかんじで他のブログサービスもピンとこず・・
じゃあ作ればいいじゃないの!!!となったわけでした。

「Nuxt.js + Contentful + Netlify」構成の概要

これに関しては、すばらしいフロントエンドエンジニアの方たちが分かりやすくまとめてくださってる記事がたくさんあるので割愛。
以下、参考にした記事を載せておきます。

そして実は、Nuxt.js + Contentful の構築方法は、Contentful 公式ドキュメントにチュートリアルとして載ってました。

基本的に公式をコピーしたらローカルでは簡単に立ち上がるんですが、Netlifyでひたすらエラーが出るんです。
Contentful 連携に使う環境変数を管理している.contentful.jsonがないよって言われるんですね。
それもそのはず、API Keyをリモートリポジトリにpushするわけにはいかないので、gitignoreしてるからです。
ということは、gitignoreしてるファイルをimportした時点でエラる!
つまり、import(読み込ませる)記述をする必要のある gitignoreファイルでの環境変数を管理することはできない。
そこで、dotenvを使っていきます。

0. 準備

まず開発を進めるにあたる準備をそれぞれやっていきます。

Nuxt.js

github にリポジトリを登録し、Nuxt.js開発環境の基礎を作成します。

参考にした記事:

Contentful

Contentful に登録、ログインし、管理画面で以下を済ませておきます。

  • Space の作成
  • Content Model の作成
  • API Key の作成

参考にした記事:

Netlify

参考にした記事:

1. dotenvで環境変数を管理する

ではではやっていきます。

まずdotenv をインストールします。

$ npm i dotenv

nuxt.configと同階層に.envファイルを作成し、以下のようにcontentful のAPI Keyなどを変数で置きます。

// ./.env

CTF_PERSON_ID=<<15jwOBqpxqSAOy2eOO4S0m>>
CTF_BLOG_POST_TYPE_ID=<<blog>>
CTF_SPACE_ID=<<YOUR_SPACE_ID>>
CTF_CDA_ACCESS_TOKEN=<<YOUR_ACCESS_TOKEN(Content Delivery API - access token)>>

補足

先ほどの公式チュートリアルのページに、環境変数として何を用意する必要があるか書いてあります。

Now you have to define the used environment variables. To avoid the need for setting all the environment variables in the CLI when running e.g. npm run dev you can set up a new config file called .contentful.json. This file includes the needed configuration:

the entry ID of the person (the owner of the blog)
the content type ID of blog posts to fetch the posts data
your space ID
the content delivery access token
You already used the space ID (CTF_SPACE_ID) and the access token (CTF_CDA_ACCESS_TOKEN). The content type ID for blog posts and the entry ID of the one person who is the author of the blog are already defined in the template data. The ID of the blog posts will be blogPost and the ID of the perosn is 15jwOBqpxqSAOy2eOO4S0m.

2. Contentful の連携

さあ本題。Contentful の連携をしていきます。

まずはContentful のインストールから。

$ npm install --save contentful

次に、Contentful を管理するjsを用意。これは公式のまんまです。

// ./plugins/contentful.js

const contentful = require('contentful')
// use default environment config for convenience
// these will be set via `env` property in nuxt.config.js
const config = {
  space: process.env.CTF_SPACE_ID,
  accessToken: process.env.CTF_CDA_ACCESS_TOKEN
}

// export `createClient` to use it in page components
module.exports = {
  createClient () {
    return contentful.createClient(config)
  }
}

前述の通り、公式チュートリアルでは.contentful.jsonで管理してますが、それだとNetlify でエラーになっちゃうのでdotenv で管理してます。
よって、nuxt.config.js は以下のようにします。

// ./nuxt.config.js

const config = {
  head: {
    title: 'nuxt_blog',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Nuxt.js project' }
    ],
    link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } ]
  },

  loading: { color: '#3B8070' },

  build: {
  },

  plugins: [
    { src: '~plugins/contentful' }
  ],

  env: {
    baseUrl: process.env.BASE_URL || 'http://localhost:3000',
    CTF_PERSON_ID: process.env.CTF_PERSON_ID,
    CTF_BLOG_POST_TYPE_ID: process.env.CTF_BLOG_POST_TYPE_ID,
    CTF_SPACE_ID: process.env.CTF_SPACE_ID,
    CTF_CDA_ACCESS_TOKEN: process.env.CTF_CDA_ACCESS_TOKEN,
  }
}

module.exports = config

参考にした記事:

3. 記事タイトルと本文を表示してみる

これもほぼ公式のままだったかな?

// ./pages/index.vue

<template>
  <div>
    <p>coming soon!</p>

    <section class="container">
      <ul>
        <li v-for="(post, index) in posts" :key="index">
          <p>{{ post.fields.title }}</p>
          <p>{{ post.fields.body }}</p>
        </li>
      </ul>
    </section>

  </div>
</template>

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

  const client = createClient()

  export default {
    // `env` is available in the context object
    asyncData ({env}) {
      return Promise.all([
        // fetch the owner of the blog
        client.getEntries({
          'sys.id': env.CTF_PERSON_ID
        }),
        // fetch all blog posts sorted by creation date
        client.getEntries({
          'content_type': env.CTF_BLOG_POST_TYPE_ID,
          order: '-sys.createdAt'
        })
      ]).then(([entries, posts]) => {
        // return data that should be available
        // in the template
        return {
          person: entries.items[0],
          posts: posts.items
        }
      }).catch(console.error)
    }
  }
</script>

すると・・

できたー!

4. Netlifyで公開する

これまたNetlify の使い方をまとめてある記事はいっぱいあるので、ここでは私が参考にした記事をまとめておきます。

  • Netlify.toml でNetlify の デプロイ設定を管理できるみたい。

* Contentful webhockの設定

あとは、Contentful でデータを作成したたびにpublish される仕組みを作れば完成です✨
ここはまだできてないので、今後やってみようと思ってます。

参考になりそうな記事:

おわり。