🎖️

Next.js App router + microCMSで画像を含んだコンテンツを表示する

2024/06/04に公開

はじめに

Next.js App router + microCMSで次のように画像を含んだコンテンツを表示する方法を記述しております。

参考にさせていただきました。
https://zenn.dev/microcms/articles/a953f46a839ee7

microCMSとは

microCMSは日本発のヘッドレスCMS(Content Management System、コンテンツ管理システム)です。
microCMSはAPIベースで動作し、ウェブサイトやアプリケーションに動的コンテンツを提供しています。
https://microcms.io/

ヘッドレスCMS

フロントエンドの表示部分(ヘッド)とバックエンドのデータ管理部分が分離されているシステムのことを指します。

APIの作成

一から作成する

サービス名とサービスIDを入力して、サービスを作成する

サービスにアクセスする

自分で決める

入力して次へ

リスト形式を選択し、次へ

APIスキーマを作成したら、作成を押してください。

コンテンツの作成

追加を押してください。

OKを選択してください。

SDKのインストール

microCMSのAPIを簡単に利用するためのSDK((Software Development Kit))をインストールしてください。
https://www.npmjs.com/package/microcms-js-sdk

npm install microcms-js-sdk

プロジェクトのルートディレクトリlibs/client.jsを作成してください。

mkdir libs && touch libs/client.js

microCMS APIとの接続するための設定を記述してください。

libs/client.js
import { createClient } from 'microcms-js-sdk';

export const client = createClient({
  serviceDomain: process.env.NEXT_PUBLIC_SERVICE_DOMAIN_ID || '',
  apiKey: process.env.NEXT_PUBLIC_API_KEY || '',
});

下記の黒枠の部分です。

APIルートの作成

X-Microcms-Api-KeyでAPIキーが確認できてしまうので、APIのルートを作成してクライアントサイドではなく、サーバーサイドでリクエストを送るようにします。

route.tsファイルを作成してください。

mkdir -p src/app/api/microCMS && touch src/app/api/microCMS/route.ts

詳しくはこちらの記事を確認してください。
https://zenn.dev/nenenemo/articles/59ca1b03fcf234

src/app/api/microCMS/route.ts
import { NextResponse } from 'next/server';
import { client } from '../../../../libs/client';

export async function GET() {
  try {
    const res = await client.get({
      endpoint: process.env.END_POINT || '',
    });

    return NextResponse.json(res, { status: 200 });
  } catch (error) {
    throw error;
  }
}

microCMSのAPIからデータを取得する

src/app/page.tsx
'use client';
import axios from 'axios';
import Image from 'next/image';
import { useEffect, useState } from 'react';

interface Image {
  createdAt: string;
  id: string;
  image: {
    url: string;
    height: number;
    width: number;
  };
  publishedAt: string;
  revisedAt: string;
  text: string;
  title: string;
  updatedAt: string;
}

export default function Home() {
  const [data, setData] = useState<Image[]>([]);

  useEffect(() => {
    const getData = async () => {
      try {
        const response = await axios.get('/api/microCMS');
        setData(response.data.contents);
      } catch (error) {
        if (axios.isAxiosError(error)) {
          console.error('Axiosのエラーが発生しました:', error);
        } else {
          console.error('Axios以外のエラーが発生しました:', error);
        }
      }
    };

    getData();
  }, []);

  return (
    <main>
      {data.length > 0 && (
        <main>
          <div className='flex'>
            {data.map((item, index) => (
              <div key={index} className='flex-grow'>
                <h3>{item.title}</h3>
                <Image
                  src={item.image.url}
                  alt={item.title}
                  width={200}
                  height={100}
                  priority
                />
                <p>{item.text}</p>
              </div>
            ))}
          </div>
        </main>
      )}
    </main>
  );
}

環境変数の設定

.envファイルを作成してください。

touch .env
.env
NEXT_PUBLIC_SERVICE_DOMAIN_ID='<サービスID>'
NEXT_PUBLIC_API_KEY='<APIキー>'

END_POINT='<エンドポイント>'

APIキーは、権限管理から確認できます。

URLパターンの指定

このままでは画像が表示されないと思います。
下記のように指定されたパターンにマッチする画像URLから画像を取得して最適化を行うことを許可してください。

next.config.mjs
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.microcms-assets.io',
      },
    ],
  },
};

export default nextConfig;

remotePatternsについては下記を参考にしてください。
https://zenn.dev/nenenemo/articles/082ac7dcffe308#remotepatterns

ローカルの開発環境でコンテンツの変更が反映されない

https://help.microcms.io/ja/knowledge/app-router-cache

下記コマンドで.next/cacheディレクトリ内のキャッシュが削除すると反映されました。

rm -rf .next/cache

毎回手動でキャッシュを削除するのは大変なので、コマンドを修正しました。

package.json
    "dev": "rm -rf .next/cache && next dev",

コンテンツの変更が反映されない問題について、.next/cacheディレクトリ内のキャッシュが削除する以外にわからなかったので、キャッシュを無効にする方法などご存知の方はコメントで教えていただけると助かります。

またクライアントサイドのみでデータを取得するようにしているものを、ビルドしてS3にアップロードしたところ問題なく、コンテンツの変更は反映されていました。

終わりに

何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉

Discussion