K1ファクトリー
WordPressをヘッドレスCMSとして利用してNext.jsで表示(REST API編)

WordPressをヘッドレスCMSとして利用してNext.jsで表示(REST API編)

国産ヘッドレスCMSの「microCMS」を使ったほうがシンプルでやりやすいけど、
世の中、すでにWordPressだらけなので、
すでにあるWordPressを利用して、JAMstack化というのが
ユーザー的にはとっかかり易いみたい。
それに、WordPressの管理画面なら慣れてるし。

WordPressってREST APIってのが標準であるそうで、
https://WordPressサイト/wp-json とブラウザで打ち込むと、
ブログがJSONデータで表示されるんです。

それを利用して、Next.jsでブログを表示させようというもの。

今回は、「A JavaScript Client for the WordPress REST API」
略して node-wpapi !?というライブラリをつかって、
WordPressの REST API から、ブログ表示させてみた。
Next.jsのSSGモードでWordPressの記事一覧と詳細を表示する
を参照というか、使わせていただきました。

node-wpapi をインストール

$ npm install node-wpapi


まず、ブログ一覧ページ「index.js」から。
pages/index.js です。

// node-wpapiをインポート
import WP from 'wpapi'
import Link from 'next/link'

// 読み込む WordPress REST APIのエンドポイントを指定します。
// API_URLは、.envファイルに。。
const wpClient = new WP({
  endpoint: process.env.API_URL
})
  
// 出力部分
export default function Home(props) {
  return (
    <div>
        <h1>ブログ記事一覧</h1>
        <ul>
          {props.posts.map(post => (
            <li key={post.id}>
              <Link href={`/posts/${post.slug}`}>
                <a>
                  {decodeURI(post.title.rendered)}
                </a>
              </Link>
            </li>
          ))}
        </ul>
    </div>
  )
}

export const getStaticProps = async () => {
  const data = await wpClient.posts().perPage(100) // perPage()で表示ページ数指定
  return {
    props: {
      posts: data
    }
  }
}


リンクのタイトル部分が日本語で、そのままだとエンコードされちゃってるので、
デコードしてやります。decodeURI(post.title.rendered)

wpClient.posts().perPage(100)
perPage(100) --> 100件記事表示ということです。
こういうオプション的なことができます。
ほかにもあるので、
Requesting Different Resources から下を参照してください。


次に、各記事個別ページです。
場所は、
pages/posts/[slug].js とします。

// index.js とおなじく。
import WP from 'wpapi'
import Link from 'next/link'

const wpClient = new WP({
 endpoint: process.env.API_URL
})

// 各記事([slug].js)では、getStaticPathsとgetStaticPropsが必要です。
// getStaticPathsのほうは、URLを動的に作ってるとのこと。
export const getStaticPaths = async () => {
 const posts = await wpClient.posts()
 return {
  paths: posts.map(post => ({
   params: {
    slug: post.slug
   }
  })),
  fallback: false
 }
}

// getStaticPropsのほうは、ページ内のコンテンツを動的に取得してるそうです。
export const getStaticProps = async ({ params }) => {
 const posts = await wpClient.posts().slug(params.slug)
 return {
  props: {
   post: posts[0]
  }
 }
}

// HTML出力部分です。
export default function MyPost({ post }) {
 return (
  <div>
   <article>
    <h1>{post.title.rendered}</h1>
    <div dangerouslySetInnerHTML={{ __html: post.content.rendered }} />
   </article>
   <Link href="/">Back</Link>
  </div>
 )
}

titleexcerpt、そして content は、.renderedが必要です。
post.title.rendered てな具合とします。

content などリッチテキストとして入力したものは、
dangerouslySetInnerHTML={{ __html: post.content.rendered }}
としてやらないと、HTMLタグのまま出力されてしまいます。

これで、最低限のブログ一覧と各記事詳細を表示できますね。

以上の方法でとりあえず出来ましたけど、
アイキャッチ画像は普通にやってもREST APIで取得出来なくて、
エンドポイントに「?_embed」とかを追加する必要があるんですが、
node-wpapi でのやり方がわからなかったので、
WordPress の function.php を弄って、APIに項目を追加して表示させたりしました。
それについては、また今度ご紹介します。

HTML is loading comments...