こんにちは!
株式会社SCOUTER開発部フロントエンドエンジニアの佐藤(@r_sato1201)です
先日、社内でプログラミング歴が浅い社員対象の、初学者LT大会というものが開催されました。
LT大会の様子は後日このブログにて公開されると思いますが、
今回はそのLT大会で私が作成したものを、使った技術の紹介も含めて紹介したいと思います。
主にNuxtとNetlifyについて紹介します。
作成物
休日に活動しているバンドのHPを作成しました。
技術構成
Nuxt + Contentful + Netlify
この構成を選んだ理由は大きく2点あります。
HPの更新を誰でも更新できるようにしたかった
バンドHPでは主に、ライブ情報や発売したCDなどの情報を定期的に更新する必要があります。 その更新を、私以外のバンドメンバーでも更新できるようにしたかった為、CMS化することを考えました。 その中で、ContentfulはAPIファーストでコンテンツの作成・管理を簡単にできるので選択しました。
サーバーを自前で用意・運用したくなかった
上記の通りなのですが、サーバーを自前で運用するのはコストもかかりますし、知見もなかったので 静的サイトホスティングサービスであるNetlifyを選択しました。 GitHubリポジトリからwebhookを受け取ると自動でリポジトリをビルドやデプロイしてくれるので非常に便利なサービスです。
1.Nuxtでサイトの作成
Nuxtプロジェクト作成
yarn create nuxt-app <プロジェクト名>
まずは上記コマンドでNuxtプロジェクトを作成します。
layoutの作成
各ページ共通であるヘッダー、フッターをレイアウトテンプレートに記述しました。
default.vue
<template> <div> <Header/> <nuxt/> <Footer/> </div> </template> <script> import Header from '~/components/item/Header.vue' import Footer from '~/components/item/Footer.vue' export default { components: { Header, Footer, }, } </script>
ヘッダー、フッター部分のコードは割愛します。
Contentfulの設定
Contentfulについて
Nuxtでプロジェクトを作り、外見をつくったら次はContentfulの設定です。 Contentfulはコンテンツを管理するためのREST APIを提供してくれます。
Contentfulの概念は上図のようになっています。
各々をイメージで説明すると
Space:コンテンツを管理する単位
ContentModel:データベースのテーブル定義のようなもので、テーブルのカラム定義を設定する場所
Entry:ContentModelに定義したテーブルのデータ
となります。
Spaceの作成→ContentModelの作成→Entryの作成という順序でコンテンツを作成します。
次に、Contentfulを呼び出す用のプラグイン、contentful.js
を作成します
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) }, }
次に、Contentfulと接続するためのAPI keyを取得し、接続設定を以下のように.env
に記述します
.env
CTF_SPACE_ID="Your Space ID" CTF_CDA_ACCESS_TOKEN="Your Access Token" CTF_BLOG_POST_TYPE_ID="Your Post Type ID"
nuxt.config.jsにて先程.env
に記述した内容をenvプロパティにて呼び出します。
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_BLOG_POST_TYPE_ID: config.CTF_BLOG_POST_TYPE_ID } // ... }
最後に、Vueファイルを記述し記事を取得します。
asyncData
内でContentfulから記事情報を取得し、Liveコンポーネントに渡しています。
※Vueファイルは分かりやすくするため、簡略化しています
pages/live/index.vue
<template> <div class="container"> <live v-for="post in posts" :key="post.fields.slug" :image="post.fields.image" :title="post.fields.title" :place="post.fields.place" :fee="post.fields.fee" /> </div> </template> <script> import Live from '~/components/Live' import { createClient } from '~/plugins/contentful' const client = createClient() export default { transition: 'slide-left', components: { Live, }, asyncData({ env }) { return client .getEntries({ content_type: env.CTF_BLOG_POST_TYPE_ID, order: '-fields.date', }) .then(entries => { return { posts: entries.items, } }) .catch(console.error) }, } </script>
components/Live.vue
<template> <div class="live-card"> <div class="live-card_image"> <img :src="image.fields.file.url"> </div> <div class="live-card_contents"> <p class="live-card_title">{{ title }}</p> <p class="live-card_place">{{ place }}</p> <p class="live-card_fee">{{ fee }}</p> </div> </div> </template> <script> export default { props: { image: { type: Object, }, title: { type: String, }, place: { type: String, }, fee: { type: String, }, } }
これでContentfulの設定は完了しました。
※詳しくは、Contentful公式ドキュメントに詳しく書かれているので参照して下さい。
Netlifyの設定
Netlify Formsについて
Netlifyを選んだ理由として、サーバーレスで実装できる以外にもフォームが簡単に実装できることが挙げられます。
HTMLの