はじめまして、新卒1年目フロントエンドエンジニアのフジタです。
今回はNuxt.jsで個人的にブログサイトを作成しているのでそれについてまとめていこうと思います。
Nuxt.jsとは
SSR(サーバーサイドレンダリング)に対応したVue.jsのフレームワークです。僕はSSRって聞くとなんだかワクワクします。
まだまだ勉強中なので詳しく知りたい方は公式ドキュメントをご覧ください。
SSR(サーバーサイドレンダリング)とは
SPA(シングルページアプリケーション)などでブラウザで行われていたJSの実行とHTML生成をサーバー側で行う技術です。
動作の流れとしては以下です。
- クライアント側からHTTPリクエストが送られる(差分のみ)
- サーバーが更新されたHTMLを生成してクライアント側に返す
- ブラウザ側でHTMLを表示
差分のみのHTTPリクエストが送信されるのはSPAも同じです。SPAとの違いはHTMLの生成をブラウザ側で行わずにサーバー側で行う点にあります。
メリットとしてSEOの向上、ユーザーの通信環境に左右されにくいことが挙げられます。
検索エンジンのクローラが完全に描画されたページを直接解析するため、SEO が向上します。
(中略)
特にインターネットの遅さや遅いデバイスでは、コンテンツの再生時間が短縮されます。サーバで描画されたマークアップは、すべての JavaScript がダウンロードされて表示されるまで待つ必要がないので、ユーザは完全に描画されたページをすぐに見ることができます。
デメリットはサーバー側の負担が大きくなることやNode.jsが実行できるサーバーを用意する必要があることが挙げられます。
- より複雑なセットアップと開発の要件を構築します。静的ファイルサーバに展開できる完全静的 SPA とは異なり、サーバで描画されたアプリケーションでは Node.js サーバを実行できる環境が必要になります。
- サーバ側の負荷が増えます。 Node.js の完全なアプリケーションを描画することは、静的ファイルを提供するだけでなく、CPU を多用することになるので、トラフィックが多いことが見込まれる場合は、対応するサーバの負荷に備え、キャッシュの対策を賢明に行なってください。
Nuxt.js以外に使うもの
- Netlify
- 静的サイトをホスティングすることができるWebサービス。超便利
- Contentful
- ヘッドレスCMS(ビューのないCMS)
- ブログ記事のコンテンツ管理に使用します
ヘッドレスCMSをふわっと説明
通常のCMS(WordPressとか)はWebページ(フロントエンド)と管理(バックエンド)が1つに統合されています。ヘッドレスCMSはその2つを分けようという構造から生まれたCMSです。
つべこべ言わずに環境構築していく
create-nuxt-app を使う
すぐ始めたいのでcreate-nuxt-appを使用します。
※コマンド入力した後に色々選択します。(今回は省略)
$ npm -v
6.9.0
$ npm init nuxt-app sample-blog
起動できた
依存関係をインストール後、プロジェクトのフォルダにいきnpm run dev
をすると起動します。今回は試しにVuetifyを使ってみようと思い選択したので起動画面がいつもと違いました。びっくりした。
仮でコンテンツの実装をする
一旦仮で記事コンテンツの実装をします
<template>
<v-card class="card mb-5">
<nuxt-link
:to="{ name: 'blog-slug'}"
class="wrapper"
>
<v-card-title>記事タイトル</v-card-title>
<v-card-text>
<v-row
align="center"
class="mx-0"
>
</v-row>
<div>記事の概要</div>
</v-card-text>
</nuxt-link>
</v-card>
</template>
<style lang="scss" scoped>
.wrapper {
text-decoration: none;
}
</style>
<template>
<v-container class="index">
<card
v-for="i in 5"
:key="i"
/>
</v-container>
</template>
<script>
import Card from '~/components/card.vue'
export default {
components: {
Card
}
}
</script>
<template>
<v-container class="slug">
<h1 class="slug_title">
タイトル
</h1>
<p class="slug_date">2020/12/14</p>
<div>
記事の内容
</div>
</v-container>
</template>
nuxt.config.js
でデフォルトでテーマが設定されているので背景が黒いですが、白だと同化してしまうのでそのままにしておきます。
Vuetifyのおかげですでにそれっぽく見えますね^^
contentfulの設定をする
ログインする
こちらからログインできます。
コンテンツを作成する
- 上部の
Content model
からAdd content type
で作成 - modalが出てくるので入力して作成
modelを使用してコンテンツを追加する
上部のContent
からAdd [type名]
でコンテンツを何個か作成します。
Contentfulをnuxtプロジェクトに追加する
$ npm add --dev contentful
以下、設定ファイルです。
require('dotenv').config()
function getValidConfig(configEnv, keys) {
let { config, missingKeys } = keys.reduce(
(acc, key) => {
if (!configEnv[key]) {
acc.missingKeys.push(key)
} else {
acc.config[key] = configEnv[key]
}
return acc
},
{ config: {}, missingKeys: [] }
)
if (missingKeys.length) {
throw new Error(`Contentful key is missing : ${missingKeys.join(', ')}`)
}
return config
}
module.exports = {
getConfigForKeys(keys) {
const configEnv = {
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
}
return getValidConfig(configEnv, keys)
}
}
const contentful = require('contentful')
const defaultConfig = {
CTF_SPACE_ID: process.env.CTF_SPACE_ID,
CTF_CDA_ACCESS_TOKEN: process.env.CTF_CDA_ACCESS_TOKEN
}
module.exports = {
createClient(config = defaultConfig) {
return contentful.createClient({
space: config.CTF_SPACE_ID,
accessToken: config.CTF_CDA_ACCESS_TOKEN
})
}
}
import colors from 'vuetify/es5/util/colors'
const pkg = require('./package')
const { getConfigForKeys } = require('./lib/config.js')
const ctfConfig = getConfigForKeys([
'CTF_BLOG_POST_TYPE_ID',
'CTF_SPACE_ID',
'CTF_CDA_ACCESS_TOKEN'
])
const { createClient } = require('./plugins/contentful')
const cdaClient = createClient(ctfConfig)
export default {
// 省略
generate: {
routes() {
return cdaClient
.getEntries(ctfConfig.CTF_BLOG_POST_TYPE_ID)
.then(entries => {
return [...entries.items.map(entry => `/blog/${entry.fields.slug}`)]
})
}
},
env: {
CTF_SPACE_ID: ctfConfig.CTF_SPACE_ID,
CTF_CDA_ACCESS_TOKEN: ctfConfig.CTF_CDA_ACCESS_TOKEN,
CTF_BLOG_POST_TYPE_ID: ctfConfig.CTF_BLOG_POST_TYPE_ID
}
// .env
CTF_SPACE_ID=<Contentfulで記載されているspace_id>
CTF_CDA_ACCESS_TOKEN=<Contentfulで記載されているアクセストークン>
CTF_BLOG_POST_TYPE_ID=<contentfulで記載されているポストタイプ>
Contentfulに対応したコンテンツの内容に書き換える
<template>
<v-card class="card mb-5">
<nuxt-link
:to="{ name: 'blog-slug', params: {
sys: id
}}"
class="wrapper"
>
<v-card-title>{{ title }}</v-card-title>
<v-card-text>
<v-row
align="center"
class="mx-0"
>
</v-row>
<div>{{ date }}</div>
</v-card-text>
</nuxt-link>
</v-card>
</template>
<script>
export default {
props: {
title: {
type: String,
default: ''
},
id: {
type: String,
default: ''
},
date: {
type: String,
default: ''
}
}
}
</script>
<style lang="scss" scoped>
.wrapper {
text-decoration: none;
}
</style>
<template>
<v-container class="index">
<card
v-for="(post,i ) in posts"
:key="i"
:title="post.fields.title"
:id="post.sys.id"
:date="post.sys.updatedAt"
/>
</v-container>
</template>
<script>
import Card from '~/components/card.vue'
import { createClient } from '~/plugins/contentful.js'
const client = createClient()
export default {
transition: 'slide-left',
components: {
Card
},
asyncData({ env, params }) {
return client
.getEntries(env.CTF_BLOG_POST_TYPE_ID)
.then(entries => {
return {
posts: entries.items
}
})
.catch(console.error)
}
}
</script>
<template>
<v-container class="slug">
<h1 class="slug_title">
{{ article.fields.title }}
</h1>
<p class="slug_date">{{ article.sys.updatedAt }}</p>
<div>
{{ article.fields.body.content[0].content[0].value }}
</div>
</v-container>
</template>
<script>
import { createClient } from '~/plugins/contentful.js'
const client = createClient()
export default {
props: {
id: {
type: String,
default: ''
}
},
transition: 'slide-right',
async asyncData({ env, params }) {
return await client
.getEntry(params.sys)
.then(entrie => {
return {
article: entrie
}
})
.catch(console.error)
}
}
</script>
Contentfulのコンテンツを持ってこれた
Netlifyの設定をする
デプロイ
- GitHubでログインしておきます。
-
New site from Git
を押す - Gitのプロバイダーを選択する(今回はGitHub)
- Configure the Netlify app on GitHub.を押してGitHubでNetlifyと連携するリポジトリを追加する
-
Build command
とPublish directory(今回はdist)
を設定してデプロイする
ContentfulとNetlifyのWebhook連携
先ほどの.env
のキーを入力します。
完成!
最後に
以上、環境構築編でした。この後にマークダウンで記述するための設定やコーディングなどが控えているのですが、力尽きてしまったので今回はここまでになります。
次回 気が向いたらマークダウン編です。