公開日:7/5/2020 更新日:1/5/2025
本ブログの作成方法、仕組みについて詳しく解説紹介します。Nuxt.js で技術ブログを作ってみたいけど、具体的にどうやって始めたらよいのか分からない人の助けになれたら幸いです。
使用技術 | 概要 |
---|---|
Nuxt.js | Vue.js に基づいたプログレッシブフレームワーク。ブログサイト等を簡単に作れる。 |
microCMS | APIで記事をJSON形式で取得できる日本製のHeadlessCMS。 |
Netlify | 静的なサイトのホスティングサービスで、ビルドからデプロイ、ホスティングなどを全て賄ってくれる。 |
JAMstack とは、javascript, API, Markup の頭文字をとった造語で、これらの組み合わせで構成されるアーキテクチャの総称です。javascript がクライアントサイドを担当し、APIサーバとデータのやりとりをします。マークアップはジェネレーター等により静的な資材として吐き出されたテンプレートを指します。
上記技術を用いて、JAMstackなブログ開発をする手順を具体的に示します。
本記事の手順を真似れば、本ブログのようなサイトが出来上がります (完成度低いですが) 。
microCMS とは、登場してまだ日が浅い日本製HeadlessCMSサービスです。記事は管理画面から管理作成でき、記事ごとに生成されたAPIを叩くことで、JSON形式の記事データを取得することが出来ます。microCMS は日本製なので公式HPが日本語で理解しやすく、ブログ作成に必要な機能も充実しています。
まず最初は、microCMS に新規アカウント登録します。
こちら(microCMSのはじめ方) の本家記事にmicroCMSの始め方について説明があるので、詳しく知りたい方は参照して下さい。
今回は趣味の範囲でのブログ作成なので、無料枠で登録します。本ブログも無料枠を使用しています。
サービス名とサービスIDを決めてサービス登録が済んだら、次にリスト形式のAPIの作成にとりかかります。
以下のようにAPIスキーマで管理する各フィールドを作成して下さい。
必要最低限なフィールドとして、記事タイトルと記事コンテンツを用意しています。後々開発を進めていく中で、記事タイトル画像やカテゴリなどのフィールドを必要に応じて適宜追加していって下さい。今回は下記のように、テスト用にブログ記事を簡略に3つ用意しました。
microCMSの管理画面の右上にあるAPIプレビューで、さきほど作成した記事を取得する API リファレンスが参照できます。X-API-KEYをヘッダーに追記し、GETリクエストを送ると記事に関するJSONデータが返却されていることが分かると思います。
まずは、node.jsをインストールして下さい。
Windowsの人はここからインストール
npm --version
上記コマンドでバージョンが表示されたらオーケーです。私は ver 6.14.4 をインストールしてます。
次に、プロジェクト用のフォルダを用意してからNuxtのプロジェクトを作成します。
mkdir test-blog
cd test-blog
npm install -g @vue/cli
npx create-nuxt-app
質問に答えて下さい。
create-nuxt-app v3.4.0
✨ Generating Nuxt.js project in .
? Project name: test-blog
? Programming language: JavaScript
? Package manager: Npm
? UI framework: Bootstrap Vue
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/JAMStack hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? What is your GitHub username? xxxx
? Version control system: Git
さっそく、サーバを立ち上げてみましょう。
npm run dev
http://localhost:3000/ に無事アクセスできたらオーケー。
さっそくコーディングしていきましょう。 まず、APIでmicroCMSとやり取りする際に必要となるAPIキーを .envファイルから環境変数として取得する処理を書いていきます。セキュリティの観点からAPIキーをコードにベタ書きしない方針ですね。dotenv のモジュールを使用するので、以下の npm コマンドでモジュールをインストールします。PromiseベースのHTTPクライアントaxiosも後に必要になるので、一緒にインストールしましょう。
npm install --save @nuxtjs/dotenv
npm install --save axios
./test-blog/.env を新規作成します。.envファイルに、microCMSの管理画面から確認できる自分のAPI_KEYを設定して下さい。
//.env
API_KEY=××××××××××××××××××
nuxt.config.jsに環境変数と axios を使用するために以下を追記します。
//追記
require("dotenv").config();
const { API_KEY } = process.env;
const axios = require("axios");
----------------------------------------------------
//追記
env: {
API_KEY
},
次に ./test-blog/index.vue を修正します。以下のように、index.vue を丸々書き換えて下さい。URL のxxxxの部分はご自身が登録したmicroCMSの設定値に変更して下さい。asyncDataメソッドにより記事一覧のJSONをmicroCMSより取得、v-for ディレクティブにより展開しています。
<template>
<div>
<h1>test-blog</h1>
<div v-for="(item,key) in items" :key="key">
<h2>{{ item.title }}</h2>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
items: []
};
},
async asyncData() {
const { data } = await axios.get(
"https://xxxxx.microcms.io/api/v1/article",
{
headers: { "X-API-KEY": process.env.API_KEY }
}
);
return {
items: data.contents
};
}
}
</script>
<style>
h1 {
display: block;
font-size: 3em;
text-align: center;
font-weight: bold;
border-top: solid 3px #364e96;
border-bottom: solid 3px #364e96;
}
h2 {
display: block;
font-size: 1.6em;
text-align: center;
font-weight: bold;
border: solid #ddd;
border-width: 0 0 1px 0;
}
</style>
上手くいくと、下記のようにブログタイトルと記事見出しの一覧が表示されます。
管理画面にて記事をhtml形式やマークダウン形式で公開した場合、素のままだとhtmlタグがそのまま出力されます。 なので、@nuxtjs/markdownit を導入してマークダウン形式で記事を管理・表示できるようにします。
npm install --save @nuxtjs/markdownit
次に、markdownit を導入するために nuxt.config.js に以下の設定を追記します。
//modulesに追記
modules: ['@nuxtjs/markdownit'],
//追加
markdownit: {
html: true,
injected: true,
preset: 'default',
},
./test-blog/pages/article/_id.vue を新規作成して下さい。URL のxxxxの部分はご自身が登録したmicroCMSの設定値に変更して下さい。
<template>
<div>
<h1>{{ item.title }}</h1>
<div v-html="$md.render(item.content)"></div>
<nuxt-link :to="'/'">
<h2>戻る</h2>
</nuxt-link>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
items: []
};
},
async asyncData({ params }) {
const { data } = await axios.get(
`https://xxxxx.microcms.io/api/v1/article/${params.id}`,
{
headers: { "X-API-KEY": process.env.API_KEY }
}
);
return {
item: data
};
}
};
</script>
<style>
h1 {
display: block;
font-size: 3em;
text-align: center;
font-weight: bold;
border-top: solid 3px #364e96;
border-bottom: solid 3px #364e96;
}
</style>
記事一覧ページ (http://localhost:3000/) からリンクで記事詳細ページ (http://localhost:3000/article/xxxxx) に飛べるように、index.jsに nuxt-link を追加します。
//index.js
<template>
<div>
<h1>test-blog</h1>
<div v-for="(item,key) in items" :key="key">
<nuxt-link :to="'article/' + item.id">
<h2>{{ item.title }}</h2>
</nuxt-link>
</div>
</div>
</template>
技術ブログたるもの、コードにはシンタックスハイライトが適用されたいものです。本ブログでは、markdownit と prismjs.js を使用してシンタックスハイライトと行番号を表示させていきます。まずは、prism.js をインストールします。
npm install prismjs
pluginsフォルダに ./test-blog/plugins/prism.js を新たに作成します。好きなcssテーマや、使用したい言語は各自で選んでインポートして下さい。ちなみに ./test-blog/node_modeles/prismjs/themes、./test-blog/node_modeles/prismjs/components 配下にインポート対象のファイルがあります。
//prism.js
import Prism from 'prismjs'
//好きなcssのテーマを選ぶ、私のサイトは以下のcssテーマを使用
import 'prismjs/themes/prism-okaidia.css'
//使用したい言語を適宜追加 *デフォルトではjsやcssしか使えない
import 'prismjs/components/prism-***'
import 'prismjs/plugins/line-numbers/prism-line-numbers.min.js'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'
export default Prism
nuxt.config.js のplugins に prism を追加します。
plugins: ['~/plugins/prism'],
シンタックスハイライトを有効にしたい pages でprismを読み込みます。今回は記事詳細ページを有効にしたいので、_id.vue ファイルを以下のように修正します。
//_id.vue
...
import Prism from '~/plugins/prism'
export default {
...
mounted() {
Prism.highlightAll()
},
...
}
行番号を付けるために、line-numbers のclass属性を付与。
//_id.vue
<div class="line-numbers" v-html="$md.render(item.content)"></div>
これでシンタックスハイライトと、コードブロックに行番号が出現しました。
GitHub のリポジトリへ test-blog のソースコードをpushします。GitHubアカウントを持っていない人はアカウントを作成して下さい。新規作成したリモートリポジトリ (test-blog) にソースコードを push します。これでリモートリポジトリにソースコードをアップロードできました。
cd test-blog
git init
git add *
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/ユーザー名/test-blog.git
git push -u origin main
Netlify とは静的ホスティングサービスです。npm run generate コマンドを実施して、./test-blog/dist フォルダ配下に吐き出された静的ファイルをホスティングしてくれます。なので、静的ジェネレイトを実行するための動的パス設定を nuxt.config.js に追記する必要があります。
generate: {
routes() {
const blog = axios
.get("https://myfirstblog.microcms.io/api/v1/article", {
headers: { "X-API-KEY": process.env.API_KEY }
})
.then(res => {
return res.data.contents.map(blog => {
return "/article/" + blog.id;
});
});
return Promise.all([blog]).then(values => {
return values.join().split(",");
});
}
},
package.json のscriptsタグに、"generate": "nuxt generate"が設定されていることを確認してください。以下のように設定されていればよいです。
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
続いて、Netlifyで新規サイトを作り、GitHub連携をします。前提として、Netlifyにサインアップして、アカウントを作っておいてください。なお、サインアップする際は、GitHubアカウントで認証しておいたほうがスムーズです。「New site from Git」を押してリポジトリ選択画面に移動したのち、先ほどGithubにプッシュした名前 (test-blog) のリポジトリを選択してください。次にNetlifyへデプロイする設定を追加します。リポジトリ内でデプロイの対象となるブランチにはマスターを指定します。Build commnadには静的サイトとしてビルドするコマンド、とPublish directoryには出力されたフォルダを指定します。
Advanced build settingsからmicroCMSのAPIキーをValueに設定します。
「Deploy site」のボタンを押してエラーが出なければ無事デプロイ成功です。発行されたurl (https://xxxxxx.netlify.com) にアクセスすると、デプロイされたサイトが表示されるはずです。
microCMSの管理画面上で webhook、Netlifyでは Build hooksの設定をします。そうすることで,NetlifyがmicroCMSのAPI変更をトリガーに自動ビルドしてくれるようになります。つまり、microCMSの管理画面で記事を編集するだけで、公開されたサイトが自動で最新化されるわけです。いちいち、Git Push しなくて本番反映できるのは便利ですね。
まず Netlifyの設定画面にてSave ボタンを押下し,通知用のURLをメモします。
microCMSの管理画面にwebhookを設定します。先ほどメモしたURLを設定します。
ここから先は、私が実際にブログをエンハンスしていった過程を簡単に備忘録として残したものです。
bootstrap-vueをインストールして,ナビゲーションウィンドウを作成。headerコンポーネントを各ページに配置。
header.vue コンポーネントを下記のように作成。pages配下にリンク先のページを適宜追加。
<template>
<div class="title">
<div>
<b-navbar toggleable="lg" type="dark" variant="info">
<b-navbar-brand>テストブログ</b-navbar-brand>
<b-navbar-toggle target="nav-collapse" right></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav right>
<b-navbar-nav>
<b-nav-item href="/">ホーム</b-nav-item>
</b-navbar-nav>
<b-navbar-nav>
<b-nav-item href="/myself">自己紹介</b-nav-item>
</b-navbar-nav>
</b-collapse>
</b-navbar>
</div>
</div>
</template>
<script>
export default {
}
</script>
sns.vue コンポーネントを新規作成。
<template>
<div>
<ul class="sns">
<li>
<a :href="twitterURL" target="_blank" rel="nofollow">
<img
alt="twitter"
src="~assets/images/twitter.svg"
:width="size"
:height="size"
/>
</a>
</li>
<li>
<a :href="facebookURL" target="_blank" rel="nofollow">
<img
alt="facebook"
src="~assets/images/facebook.svg"
:width="size"
:height="size"
/>
</a>
</li>
<li>
<a :href="lineURL" target="_blank" rel="nofollow">
<img
alt="line"
src="~assets/images/line.svg"
:width="size"
:height="size"
/>
</a>
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: '',
required: true
}
},
computed: {
size() {
return 36
},
url() {
return `https://nuxtblog.xyz${this.$route.path}`
},
fixedTitle() {
return encodeURIComponent(this.title)
},
fixedContent() {
return encodeURIComponent(`${this.title} ${this.url}`)
},
twitterURL() {
return `https://twitter.com/intent/tweet?url=${this.url}&text=${
this.fixedTitle
}`
},
facebookURL() {
return `https://www.facebook.com/sharer/sharer.php?u=${this.url}&t=${
this.fixedTitle
}`
},
lineURL() {
return `http://line.me/R/msg/text/?${this.fixedContent}`
}
}
}
</script>
<style scoped>
ul.sns {
display: flex;
flex-wrap: wrap;
}
ul.sns li {
list-style-type: none;
padding: 1.5em 1.0em 0 0;
}
</style>
問い合わせページに Google フォームのHTMLコードを埋め込んで実装。こちらの記事 (GoogleフォームをWEBサイトに埋め込む方法)が参考になった。
モジュールをインポートする。
npm install --save @nuxtjs/google-analytics
nuxt.config.js に以下の設定を追記。xxxxxxxx に Google Analytics より取得したアナリティクスコード の id を設定する。
modules: [
['@nuxtjs/google-analytics', {
id: 'xxxxxxxx'
}]
]
モジュールをインポートする。
npm install --save @nuxtjs/sitemap
npm run generate を実行した際、動的ルーティングされたサイトマップ (sitemap.xml) がdistファルダに出力されるようにする。nuxt.config.js に以下の設定を追記する。
modules: [
'@nuxtjs/sitemap',
],
sitemap: {
path: '/sitemap.xml',
hostname: 'https://xxxxx',
routes (callback) {
axios.get("https://xxxxx.microcms.io/api/v1/blog", {
headers: { "X-API-KEY": process.env.API_KEY }
})
.then((res) => {
var routes = res.data.contents.map((blog) => {
return "/blog/" + blog.id
})
callback(null, routes)
})
.catch(callback)
}
本ブログの別記事 (【Nuxt.js】動的に生成されたページに個別のmetaタグを設定する方法 )にて詳しく説明している。
こちらの記事 (NuxtのJamstack構成におけるページングの実装) を参考に index.vue, _id.vue, nuxt.config.js ファイルを修正。pager.vue コンポーネントを新たに作成、現在のページ番号が active化されるようにコーディング。
//pager.vue
<template>
<div class="pager">
<ul class="pagination">
<nuxt-link :to="{ path: `/page/1`}">
<li><div class = "listcss" v-bind:class="{ active: pageNum==1}"><span>1</span></div></li>
</nuxt-link>
<nuxt-link :to="{ path: `/page/2`}">
<li><div class = "listcss" v-bind:class="{ active: pageNum==2}"><span>2</span></div></li>
</nuxt-link>
<!-- ページが増えた際に手動でliを追加する -->
</ul>
</div>
</template>
<script>
export default {
data() {
return {
//表示中のページ番号を取得する
pageNum: this.$route.params.p || '1'
}
}
}
</script>
<style scoped>
//長いので省略
</style>