見出し画像

microCMS + Next.js 14でブログページを作ってみた

この記事は「株式会社メンバーズ Jamstack研究会主催 Advent Calendar 2023」の1日目の記事です。


はじめに

昨今、Jamstackという言葉が流行をみせているのはご存知でしょうか?
フロントエンド開発を生業としているエンジニアならチラッと聞いたことがあるかもしれない単語かなと思います。

私自身JamstackなWeb制作はした事はないですが、ここまで注目度が高まっているので実際にJamstackなWeb制作をしてみたいな、と思い今回記事を書くことを決めました。

今回の記事では、お題にあるように「microCMS」と「Next.js 14」でブログサイトを作っていこうと思います。

Jamstackとは?


Jamstackという言葉は、NetlifyのMatt BiillmannとChris Bachが2015年頃に生み出したのが始まりです。
もともとは「JAMStack」と定義されていましたが、今では少し誇張されJamstackという概念に変わりました。

Jamstackの頭文字は以下の要素を含んでます。
・Javascript(主にWeb開発で活用されるプログラミング言語)
・API(Webサイトのページに表示するデータをやり取りする仕組み)
・Markup(ページを表示するためのHTMLファイル)

Tips
JamstackはWebアーキテクチャの一つで、以下のメリットを兼ね備えています。
・優れたパフォーマンス
・堅牢なセキュリティ
・柔軟性/拡張性

https://www.netlify.com/blog/the-jamstack-definition-evolved/

ヘッドレスCMS


WordPressのような従来のCMSでは、以下機能が備わっていました。
・コンテンツを作成・管理する機能
・コンテンツをWebに表示(フロントエンド(ビュワー))

一方ヘッドレスCMSは、「ヘッド(表示画面)」がないCMSで以下機能だけを持っています。
・コンテンツを作成・管理する機能

コンテンツ管理に特化することで、従来のCMSではできなかった柔軟なコンテンツ管理や自由度の高いデザインを可能としています。

microCMS


microCMSは、国産のヘッドレスCMSで豊富な実績があります。
料金プランは「Hobby」「Team」「Business」「Advanced」の4種類があります。
ドキュメントが日本語で書かれているので、初めてヘッドレスCMSを検討する方にもおすすめです。

今回は「Hobby」プランでJamstackなWeb制作を行なっていきます。

技術スタック

・microCMS
・Node.js v18.18.1
・microCMS JavaScript SDK v2.3.2
・Next.js v14.0.2
・React v18
・TypeScript v5
・ESLint v8

ゴール

・とりあえずローカル環境でmicroCMSで登録したブログ内容が表示できる

1.microCMSの準備

まずはmicroCMSのアカウントを作成とAPIの作成を行います。
参考資料: microCMSをはじめる

microCMSでサービスを作成する


microCMSホームページにアクセスし、「無料ではじめる」から無料アカウントを登録します。
無事登録が完了すると、アンケート入力画面に移動します。(スキップ可能)

アンケートに回答(スキップ)後、「microCMSへようこそ」画面が表示されるので「はじめる」ボタンを押下し、サービスを作成画面へ移動します。

サービス情報を入力する画面へ移動するので、指示に従ってサービス名とサービスIDを入力し、「サービスを作成する」ボタンを押下します。
サービスを作成画面では、「一から作成する」と「テンプレートから選ぶ」のどちらかを選択します。
今回は「一から作成する」を選択し、自分でサービスを作成していきます。

Good Point
microCMSではテンプレートを選択することができます。
テンプレート選択とは、フロントエンド部分のサンプル集のようなものです。

https://templates.microcms.io/

APIを作成する


microCMSでサービスの作成が完了したので、次はAPIを作成していきます。
いくつか選択肢がありますが、今回は「ブログ」を選択し簡易にブログAPIを作成していきます。(自動的にブログ用APIが作成されます)

API作成画面
ブログAPI作成完了

2.Next.jsプロジェクトの準備

まずは、Next.jsのプロジェクトを作成していきます。プロジェクトの雛形を作成するCLIを入力して作成していきます。

Next.jsプロジェクト作成


ターミナルで以下コマンドを入力しプロジェクトを作成します。

npx create-next-app jamstack-blog

上記コマンド入力後、ターミナル上で以下内容を確認されるので、全てYesとしてください。

Ok to proceed? (y) y
Would you like to use TypeScript?  No / Yes
Would you like to use ESLint?  No / Yes
Would you like to use Tailwind CSS?  No / Yes
Would you like to use `src/` directory?  No / Yes
Would you like to use App Router? (recommended)  No / Yes
Would you like to customize the default import alias (@/*)?  No / Yes

インストール完了後、作成したプロジェクトに移動して開発サーバーを起動します。

npm run dev

http://localhost:3000にアクセスすると無事アプリケーションを確認することができます。

初期状態アプリケーション

環境変数を用意する


microCMSへリクエストを行うために以下2つの情報が必要なので、.env.localファイルで管理します。
・serviceDomain
・apiKey
以下添付画像のオレンジ塗りが「serviceDomain」で黄色塗りが「apiKey」となります。

APIプレビュー
serviceDomainとapiKey

取得したserviceDomainとapiKeyを.env.localファイルで保護します。

// .env.local

API_KEY=xxxxxxxxxxxx
SERVICE_DOMAIN=xxxxxxxxxxxx

.env.localがうまく読み込まれていない場合、開発サーバーをもう一度立ち上げると反映が確認できます。

Enviromentsが読み込まれている状態

microcms-js-sdkの準備


今回はmicrocms-js-sdkを使用してmicroCMSからブログ情報を取得します。公式で提供しているmicrocms-js-sdkをインストールします。

npm install --save-dev microcms-js-sdk

インストール後、src配下にlibsフォルダを作成し、microcms.tsファイルを作成します。
microcms.tsでSDKの初期化を行います。.env.localで保護したserviceDomainとapiKeyを設定していきます。

// src/libs/microcms.ts

import { createClient } from 'microcms-js-sdk';

export const client = createClient({
  serviceDomain: process.env.SERVICE_DOMAIN,
  apiKey: process.env.API_KEY,
});

ブログページ作成

実際にmicroCMSからデータを取得し、ページへ表示させていきます。
Next.jsのApp Routerを使用してページを管理します。
参考資料: App Router

以下のディレクトリ構成とします。
・src/app/page.tsx => トップページ
・src/app/blog/page.tsx => 記事一覧
・src/app/blog/[blogId]/page.tsx => 記事詳細

ページ作成を行う前に、src/app/globals.cssの背景グラデーションを削除(コメントアウト)します。

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --foreground-rgb: 0, 0, 0;
  --background-start-rgb: 214, 219, 220;
  --background-end-rgb: 255, 255, 255;
}

@media (prefers-color-scheme: dark) {
  :root {
    --foreground-rgb: 255, 255, 255;
    --background-start-rgb: 0, 0, 0;
    --background-end-rgb: 0, 0, 0;
  }
}

/* body { => ここコメントアウト
  color: rgb(var(--foreground-rgb));
  background: linear-gradient(
      to bottom,
      transparent,
      rgb(var(--background-end-rgb))
    )
    rgb(var(--background-start-rgb));
} */

トップページ作成


対象ファイルに以下のように記述します。

// src/app/page.tsx

import Link from 'next/link'

export default function Home() {
  return (
    <main>
      <h1>ここはトップページです。</h1>
      <Link href='/blog'>記事一覧へ</Link>
    </main>
  )
}

ブログ一覧ページ作成


続いて、ブログ一覧ページを作成します。

// src/app/blog/page.tsx

import Link from 'next/link'
import { client } from '@/libs/microcms'
import { NextResponse } from 'next/server';

async function listBlog() {
  try {
    const response = await client.getList({
      endpoint: 'blogs',
      customRequestInit: {
        next: {
          revalidate: 0, // 0秒でページを再読み込み
        },
      }
    })

    return NextResponse.json({
      data: response.contents ?? null,
      error: null
    })
  } catch (error: any) {
    console.error('エラーが発生しました', error)
    return  NextResponse.json({
      data: null,
      error: error.message
    })
  }
}

export default async function BlogList() {
  const response = await listBlog()
  const { data, error } = await response.json()

  if(error != null) return <div>エラーが発生しました。</div>
  return (
    <main>
      <h1>ここは記事一覧ページです</h1>
      {
        <ul>
          {
            data != null ? (
              data.map((blog: {[key: string]: string}) => {
                return <li key={blog.id}>
                  <h3>{blog.title}</h3>
                  <Link href={`/blog/${blog.id}`}>詳細へ</Link>
                </li>
              })
            ) : (
              <li>データがありませんでした。</li>
            )
          }
        </ul>
      }
    </main>
  )
}

App RouterはServer Componentをベースとしているため、async/awaitが使用できます。
参考資料: https://nextjs.org/docs/app/building-your-application/routing

あとは、libs/microcms.tsのclientを呼び出してあげるだけでデータを取得することができます。

Tips
VPNを利用している場合などに、ローカルサーバーからmicroCMSにリクエストを送ると、Error: Network Errorとなる場合があります。
package.jsonのdevに「NODE_TLS_REJECT_UNAUTHORIZED=0」と追記後、「npm run dev」でサーバーを起動することでローカルからリクエストを送ることが可能になります。
※FetchAPIでリクエストを送ると詳細なエラーを確認できます
※非推奨なので、ローカル時のみ適用とすると良いでしょう

https://nodejs.org/docs/latest-v18.x/api/tls.html#tlsssl-concepts
https://nodejs.org/docs/latest-v18.x/api/cli.html#node_tls_reject_unauthorizedvalue
ローカルからリクエストを送れるようにする

ブログ詳細ページ作成


続いて、ブログ詳細ページを作成していきます。
内容は基本的にブログ一覧と同じになります。

// src/app/blog/[blogId]/page.tsx

import Link from 'next/link'
import { client } from '@/libs/microcms'
import { NextResponse } from 'next/server';
import { redirect } from 'next/navigation';


async function getBlog(blogId: string) {
  try {
    const response = await client.get({
      endpoint: 'blogs',
      contentId: blogId,
      customRequestInit: {
        next: {
          revalidate: 0,
        },
      }
    })

    return NextResponse.json({
      data: response ?? null,
      error: null
    })
  } catch (error: any) {
    console.error('エラーが発生しました', error)
    redirect('/404')
  }
}

type Blog = {
  params: {
    blogId: string
  }
}

export default async function BlogDetail({ params }: Blog) {
  const response = await getBlog(params.blogId)
  const { data, error } = await response.json()

  return (
    <main>
      <h1>ここはブログ詳ページです</h1>
      <h2>{data.title}</h2>
      <div dangerouslySetInnerHTML={{ __html: data.content }} />
      <Link href='/blog'>記事一覧へ</Link>
    </main>
  )
}

microCMSのclient.getのパラメーターにcontentIdを追加し、ブログIDを付与することで対象のブログ詳細をリクエストすることができます。

Tips
※dangerouslySetInnerHTMLはXSSを引き起こす可能性があるため非推奨とされています。
今回の構成においては、入力はmicroCMSのリッチエディタからのみであり、ユーザーからの自由入力箇所ではないため安全であるとして利用しています。
※sanitize-html を利用してサニタイズを行う方法もあります

https://ja.legacy.reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

404ページ作成


ブログ詳細ページがない場合は、404ページへリダイレクトさせます。

export default function NotFound404() {
  return (
    <main className="main">
      <p>記事が存在しません。</p>
    </main>
  );
}

おわりに

いかがだったでしょうか?
microCMSは国産のヘッドレスCMSということもあり、ドキュメントも読み易く、必要な情報を適時キャッチアップすることが容易に感じました。

Next.js 14に関しては、やはり使い易いなと改めて思いました。
今回は、CSRやFetchAPI、Vercelとの連携の紹介はしていませんが、どれも容易にできるのでぜひ試してみてください。

以上です。
今後は、Vercelとの連携なども記事にできたらいいなと思いました。
(もう少し凝ったWeb制作を行なっていきたいなと思います)

本記事が参考になれば幸いです!

#Jamstack #メンバーズ #Next .js #microCMS


この記事が気に入ったらサポートをしてみませんか?