開発

Nuxt.jsと@nuxt/contentでブログを作ろう Part1 土台作成編

作成日: 2021年8月13日

最終更新日: 2022年1月7日

目的

フロントエンド部分の柔軟なカスタマイズが可能なブログサイトを自前で作る。 記事を作成し、必要最低限表示するまでを実装する。

インストール

create-nuxt-app を使ったインストール

Create Nuxt.js App in seconds.

Nuxt.jsアプリを秒で作成

https://github.com/nuxt/create-nuxt-app

Nuxt.jsのプロジェクトを立ち上げる際は、create-nuxt-appというコマンドを用いることで対話形式でプロジェクトに必要なものを一括で揃えられる。

https://ja.nuxtjs.org/docs/2.x/get-started/installation#create-nuxt-app-を使う

※project-nameは任意の名前を設定する。

npm init nuxt-app <project-name>

インストール時の主な設定ポイント

create-nuxt-appを実行後、コマンドラインで質問に答えていく。

選択肢の中から、今回の進行上必須な項目は次の通り。

  • UI framework:
    • Tailwind CSS
  • Nuxt.js modules:
    • Content - Git-based headless CMS
  • Rendering mode:
    • Universal (SSR / SSG)
  • Deployment target:
    • Static (Static/JAMStack hosting)

Tailwind CSS

WebのUIフレームワークも一長一短で、ユーザーの操作が多いWebアプリ系に相性の良いものと、ユーザーの操作がそれほど発生しないWebページ系に相性の良いものがあると思います。

今回は後者のWebページ系に相性の良いTailwind CSSを用います。

Content - Git-based headless CMS

ブログの記事コンテンツを管理するために使う、Nuxt.js標準モジュールです。

Universal (SSR / SSG)

今回はブログのような静的なWebページを作ろうと考えているため、SSG(Static Site Gen)対応のUniversalを選びます。

Deployment target

静的なWebページを作ろうと考えているためStatic(静的)を選びます。

インストール確認

インストール後、次のコマンドを実行します。

cd <project-name>
npm run dev

ターミナルに表示されたlocalhostのアドレスを開くとページが表示されます。

コンテンツの作成

コンテンツの管理は先ほどインストール時に選択したContent - Git-based headless CMSを用います。

ContentはMarkdownをはじめとしたメジャーなデータ形式(JSON ,YAML ,XML ,CSV)を元にコンテンツとして管理提供をサポートしてくれるモジュールです。

データ形式の中から一番ブログと相性の良いMarkdownでブログサイトを構築していきます。

ここから先はNuxtJS公式のチュートリアルを参考に進めていきます。

ディレクトリ作成

contentディレクトリ内に任意の名前でディレクトリを作成(ここではarticlesとしました)

mkdir content/articles

mdファイルでコンテンツを作成

先ほど作成したディレクトリ内に任意の名前.mdファイルを作成。 このファイルがWebページ上のコンテンツの情報源となります。

例)2021-100m-final.md

# 100メートル決勝の結果
8月1日に行われた陸上100メートル男子決勝の結果まとめ

## 金メダルは史上初の…
ラモント マルチェル・ヤコブス選手が欧州新記録の9.80で金メダルを獲得。

## 銀メダルは…
F.カーリーが9.84で銀メダルを獲得。

## 感想
速かった。

表示ページの実装

先ほど作成したコンテンツを表示するためのページを準備します。

https://nuxtjs.org/blog/creating-blog-with-nuxt-content#displaying-your-content

pagesディレクトリ内に任意の名前(ここではblog)でディレクトリを作成し、_slug.vueというファイルを作成。

touch pages/blog/_slug.vue

コンテンツ取得処理

_slug.vueに次の処理を記述する。

<script>
  export default {
    async asyncData({ $content }) {
      const article = await $content('articles').fetch()

      return { article }
    }
  }
</script>

この'articles'と言う引数名はcontentディレクトリに作成したディレクトリ名と対応している。

await $content('articles').fetch()

この処理によってcontentディレクトリ内から、引数に指定したディレクトリ上のコンテンツを取得する。

表示処理

_slug.vueに次のHTMLを記述する。

<template>
  <article>
    <nuxt-content :document="article" />
  </article>
</template>

動作確認

取得処理と表示処理を記述後、ブラウザで動作確認する。

URL例)localhost:3000/blog/2021-100m-final

表示内容はmdファイルに記述した文面(本文)となる。この段階ではスタイルが未設定の素の状態で表示される。

コンテンツが持つプロパティ

ブログサイトである以上本文だけではなく、タイトルや更新日時、ページのURLなども必要になってくる。取得したコンテンツは本文のほかにデフォルトで次のようなプロパティを持っている。

  • path(ファイルのパス)
  • createdAt(作成日時)
  • updatedAt(更新日時)
  • body(本文)

これらを用いることでコンテンツの基本的な情報を表示できる。

ちなみに、表示処理で使ったnuxt-contentというコンポーネントはプロパティのうち、bodyを出力している。

追加プロパティ

先ほど紹介したプロパティは設定せずとも自動で付与される。 ここにないプロパティを任意で作成し設定することもできる。

追加方法 .mdファイルの先頭にYAML形式でブロックを追加する。

※titleやdescriptionなどプロパティ名は任意の名前で設定可能

例)2021-100m-final.md

---
title: 今日の日記
description: オリンピックの陸上100m決勝を見た感想
---

# 100メートル決勝の結果
8月1日に行われた陸上100メートル男子決勝の結果まとめ

## 金メダルは史上初の…
ラモント マルチェル・ヤコブス選手が欧州新記録の9.80で金メダルを獲得。

## 銀メダルは…
F.カーリーが9.84で銀メダルを獲得。

## 感想
速かった。

表示処理に反映

プロパティによって、本文以外の情報も手軽に実装できる。

プロパティを表示するにはarticle.titleのように記述する。

<template>
  <article>
    <h1>{{ article.title }}</h1>
    <p>{{ article.description }}</p>
    <p>Article last updated: {{ article.updatedAt }}</p>
    <nuxt-content :document="article" />
  </article>
</template>

成果物まとめ

ここまで手順通りに進めると、次の2つのファイルが出来上がります。

コンテンツ

content/articles/2021-100m-final.md

---
title: 今日の日記
description: オリンピックの陸上100m決勝を見た感想
---

# 100メートル決勝の結果
8月1日に行われた陸上100メートル男子決勝の結果まとめ

## 金メダルは史上初の…
ラモント マルチェル・ヤコブス選手が欧州新記録の9.80で金メダルを獲得。

## 銀メダルは…
F.カーリーが9.84で銀メダルを獲得。

## 感想
速かった。

記事ページ

pages/blog/_slug.vue

<template>
  <article>
    <h1>{{ article.title }}</h1>
    <p>{{ article.description }}</p>
    <p>Article last updated: {{ article.updatedAt }}</p>
    <nuxt-content :document="article" />
  </article>
</template>
<script>
  export default {
    async asyncData({ $content }) {
      const article = await $content('articles').fetch()

      return { article }
    }
  }
</script>

まとめ

ここまでで実現できたこと

  • コンテンツ作成
    • 本文の記述
    • プロパティの記述
  • 記事ページ
    • コンテンツ取得
    • コンテンツ表示
      • 本文
        • ページ上に表示
      • プロパティ
        • ページ上に表示

この先実現すべきこと

最低限ブログの仕組みを構築できましたが、まだまだ足らない部分もたくさんあります。

次の記事では以下を着手し、完成に近づけていく予定です。

  • 記事ページ
    • コンテンツ表示
      • 本文
        • CSSを当てて見やすくする
      • プロパティ
        • CSSを当てて見やすくする
        • 目次を表示する
        • 前後の記事を表示する
  • 一覧ページ
    • コンテンツ取得
      • 記事の一覧を取得
    • コンテンツ表示
      • 記事の一覧を表示
  • ホスティング
    • firebaseを使ったSSGサイトのホスティング

最後までお読みいただきありがとうございました。