GraphCMSで取得した画像が表示されなくなった時の対応とNext.jsでのコンテンツ表示

2022.04.28

こんにちは。データアナリティクス事業本部 サービスソリューション部の北川です。

GraphCMSはGraphQLクエリを使用できるヘッドレスCMSになります。

ある時Next.jsプロジェクトで、GraphCMSから取得している画像が表示されなくなったので、確認してみました。

ローカルで確認すると以下のエラーが発生していました。以前まで表示されていたので、どうやら画像のURLが変わったようです。

next.config.jsファイルを見ると、以下のようになっていました。

next.config.js

const nextConfig = {
  reactStrictMode: true,
  images: {
    domains: ["media.graphcms.com"],
  },
};

ドメインを“media.graphassets.com”に変更して再度確認してみると、しっかり表示されました。

エラーについては以上なのですが、せっかくなので、GraphCMSを使って一から画像の表示をしていきたいと思います。

GraphCMSでコンテンツの作成

graphCMSにログインし、新規にプロジェクトを作成します。

スキーマが初期設定されている便利なテンプレートもありますが、今回はBlankを選択します。

プロジェクト名、説明を入力し、リージョンを選択します。

「Free Forever」を選択します。

「Invite later」を選択します。

サイドバーから「Scheme」を選択します。

「Create Model」から「Display Name」を記述し、モデルを作成します。

スキーマを作成します。色々な型がありますが、今回は「Single line text」と「Asset picker」を選択し、それぞれ名前をtitle、imageとしました。

ちなみに、IDやCreated Atなど、自動生成されるスキーマは「Show system fields」から確認できます。

サイドバーの「Contents」から右上の「Create item」を選択し、コンテンツを作成します。

今回は、二つコンテンツを作成しました。

次に、サイドバーから「settings」内の「API Access」を選択します。 下にスクロールすると、Permissionの設定ができるので、以下のように設定します。

また、「Settings」の「Environments」からURLをコピーしておきます。

GraphCMSでコンテンツを作成することができました。次に作成したコンテンツをNext.jsプロジェクトで表示します。

ちなみに左サイドバーの「playground」でクエリ操作を行えるのですが、以前はなかったexplorer機能が追加されており、使いやすくなっていました。

Next.jsでプロジェクトの作成

プロジェクトを作成します。

$ yarn create-next-app

.env.localファイルを作成し、コピーしたURLを追加します。

env.local

NEXT_PUBLIC_GRAPHCMS_API=コピーしたAPI

libs/apollo-clients.tsファイルを作成し、ApolloClientを初期化します。

libs/apollo-client.ts

import { ApolloClient, InMemoryCache } from "@apollo/client";

export const client = new ApolloClient({
  uri: process.env.NEXT_PUBLIC_GRAPHCMS_API,
  cache: new InMemoryCache(),
});

Index.tsxを以下のように変更します。

pages/index.tsx

import type { GetServerSideProps } from "next";
import Head from "next/head";
import Image from "next/image";
import { client } from "../libs/pollo-client";
import styles from "../styles/Home.module.css";
import { gql } from "@apollo/client";
import { FC } from "react";

type Data = {
  id: string;
  title: string;
  image: { url: string };
};

export const getServerSideProps: GetServerSideProps = async () => {
  const { data } = await client.query<{ sampleModels: Data[] }>({
    query: gql`
      query MyQuery {
        sampleModels {
          id
          title
          image {
            url
          }
        }
      }
    `,
  });

  return {
    props: {
      data: data.sampleModels,
    },
  };
};

const Home: FC<{ data: Data[] }> = (props) => {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main className={styles.main}>
        <h1 className={styles.title}>
          Welcome to <a href="https://nextjs.org">Next.js!</a>
        </h1>
        <p className={styles.description}>
          Get started by editing{" "}
          <code className={styles.code}>pages/index.tsx</code>
        </p>
        <div  className={styles.grid}>
          {props.data.map((data: Data) => {
            return (
              <div key={data.title} className={styles.card}>
                <h2>{data.title}</h2>
                <Image
                  alt={data.title}
                  src={data.image.url}
                  width={250}
                  height={150}
                />
              </div>
            );
          })}
        </div>
      </main>
      <footer className={styles.footer}>
        <a
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{" "}
          <span className={styles.logo}>
            <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
          </span>
        </a>
      </footer>
    </div>
  );
};

export default Home;

next.config.jsで外部ドメインを設定します。

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  images: {
    domains: ["media.graphassets.com"],
  },
};

module.exports = nextConfig;

開発環境を立ち上げます。

$ yarn dev

GraphCMSから画像を表示することができました。

まとめ

久しぶりにGraphCMSを触りましたが、UIも綺麗で使いやすいです。ヘッドレスCMSは、日本製のMicroCMSが有名ですが、GraphQLをこれから触る方なら選択肢としていいと思います。

ではまた。