Next.js+ReactでWordPressのデータを扱ってみる

WordPressからのデータ

WordPressからのデータは、WPGraphQLをインストールしてGraphQLを使います。

WPGraphQLの設定に関しては、Next.jsの公式サンプルが参考になります。

Blog Example Using Next.js and WordPress
https://github.com/vercel/next.js/tree/canary/examples/cms-wordpress

また、GraphQLを使ったデータの取得に関しては、上記のサンプルに加えて、こちらの記事が参考になります。

How to use GraphQL variables to give queries type safety | Contentful
https://www.contentful.com/blog/2021/10/22/how-to-use-graphql-variables/

基本的には、クエリを作成して、それを使ってデータを取得することになりますが、WPGraphQLを通して取得できるデータの構成を理解する必要があります。

WPGraphQLには、GraphiQL IDEが用意されていますので、これを使ってデータ構成を確認しつつ、クエリを作成していきます(取得するデータに合わせて、ルートを選択する必要があります)。

WPGraphQLのGraphiQL IDE

ブロックテーマのTwenty Twenty-Twoを日本語環境で使っている場合、GraphiQL IDEが開けないケースがあります。英語環境に切り替えるか、Twenty Twenty-Oneなどの他のテーマに変更すれば、問題はありません。

WordPressから取得したデータをmicroCMSのデータ構成で出力する

本書で作成するプロジェクトは、microCMSから取得したデータに合わせています。そこで、microCMSのデータ構成を確認しておきます。

{
  "contents": [
    {
      "title": "スケジュール管理と猫の理論",
      "slug": "schedule",
      "publishDate": "2022-05-07T01:00:00.000Z",
      "content": "<p>何でもすぐに忘れてしまうので、予定を忘れないようにスケジュール管理手帳で予定を管理しています。でも、本当はスケジュールをスケジュールとして正しく認識できていないのかもしれません。<br></p><h2 id=\"h5dd003c520\">スケジュール管理は猫にまかせろ?</h2><p>スケジュール管理も1つのデザインです。スケジュール管理の理論として有名な本もあります。...",
      "eyecatch": {
        "url": "https://images.microcms-assets.io/assets/685...2da/schedule.jpg",
        "height": 1280,
        "width": 1920
      },
      "categories": [
        {
          "id": "design",
          "name": "デザインと設計",
          "slug": "design"
        },
        {
          "id": "fun",
          "name": "楽しいものいろいろ",
          "slug": "fun"
        }
      ]
    }
  ]
}

同様のデータをWordPressで用意します。

WordPressで用意した記事データ。タイトル、本文(見出し・段落・画像)、投稿日、スラッグ、カテゴリー、アイキャッチ画像を用意。

これをWordPressから取得した場合は、以下のような構成になります。

{
  "data": {
    "post": {
      "slug": "schedule",
      "title": "スケジュール管理と猫の理論",
      "date": "2022-05-07T10:00:00",
      "content": "\n<p>何でもすぐに忘れてしまうので、予定を忘れないようにスケジュール管理手帳で予定を管理しています。でも、本当はスケジュールをスケジュールとして正しく認識できていないのかもしれません。</p>\n\n\n\n<h2>スケジュール管理は猫にまかせろ?</h2>\n\n\n\n<p>スケジュール管理も1つのデザインです。スケジュール管理の理論として有名な本もあります。...",
      "featuredImage": {
        "node": {
          "sourceUrl": "http://xxx.xxx.xxx.xxx/wp-content/uploads/2022/08/schedule.jpg",
          "mediaDetails": {
            "height": 1280,
            "width": 1920
          }
        }
      },
      "categories": {
        "nodes": [
          {
            "name": "デザインと設計",
            "slug": "design"
          },
          {
            "name": "楽しいものいろいろ",
            "slug": "fun"
          }
        ]
      }
    }
  },
}

そこで、WordPressから取得したデータをmicroCMSのデータ構成で出力するapi.jsを用意して置き換えます。

const API_URL = 'https://xxx.xxx.xxx.xxx/graphql'

async function fetchAPI(query = '', variables = {}) {
  const response = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query,
      variables,
    }),
  }).then((response) => response.json())

  if (response.errors) {
    console.error(json.errors)
    throw new Error('Failed to fetch API')
  }
  return response.data
}

export async function getPostBySlug(slug) {
  const variables = {
    slug,
  }

  const query = `
          query getPostBySlug($slug: ID!) {
            post(idType: SLUG, id: $slug) {
              slug
              title(format: RENDERED)
              date
              content(format: RENDERED)
              featuredImage {
                node {
                  sourceUrl
                  mediaDetails {
                    height
                    width
                  }
                }
              }
              categories {
                nodes {
                  name
                  slug
                }
              }
            }
          }
        `
  try {
    const response = await fetchAPI(query, variables)

    const content = {
      title: response.post.title,
      slug: response.post.slug,
      publishDate: response.post.date,
      content: response.post.content,
      categories: response.post.categories.nodes,
    }

    if (response.post.featuredImage) {
      content.eyecatch = {
        url: response.post.featuredImage.node.sourceUrl,
        height: response.post.featuredImage.node.mediaDetails.height,
        width: response.post.featuredImage.node.mediaDetails.width,
      }
    }
    return content
  } catch (err) {
    console.log('~~ getPostBySlug ~~')
    console.log(err)
  }
}

... 長くなりますので、GitHubにアップしてあります(この記事の末尾に掲載)

これで、WordPressからのデータを使ってビルドできるようになります。ページの表示もシンプルな構成の記事であれば、大きな問題も生じません。

WordPressからのデータを使ってNext.jsでビルドしたサイト。
本文中の画像のコードを見ると、WordPressからのデータであることがわかります。

ただし、Gutenbergを本格的に活用している場合は、PostBodyコンポーネントのCSSをGutenbergに合わせて調整する必要があります。このあたりは、Gutenbergに対応したWordPressのテーマを作成する場合と同様です。


こんな感じで、異なるソースからのデータも簡単に扱えるのが、Jamstack構成の魅力だと思います。

また、データ構成を揃えたことで、WordPressかmicroCMSかのどちらか一方を選択するだけでなく、どちらも使うといった選択も出てきます。

たとえば、WordPressで管理していたこれまでのデータはそのまま残しつつ、新しいデータはmicroCMSで管理するといったこともシンプルに実現できます。

Next.jsを使って、色々とチャレンジしてみてはいかがでしょう。

テスト用にWordPress用のapi.jsと、WordPressの記事のインポートデータをGitHubに用意しました。

https://github.com/ebisucom/next-react-website-wordpress

インポートデータは「添付ファイルをダウンロードしてインポートする」をチェックしてインポートすることで、画像も合わせてインポートできます。

関連記事