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>
)
}
title や excerpt、そして content は、.renderedが必要です。
post.title.rendered てな具合とします。
content などリッチテキストとして入力したものは、
dangerouslySetInnerHTML={{ __html: post.content.rendered }}
としてやらないと、HTMLタグのまま出力されてしまいます。
これで、最低限のブログ一覧と各記事詳細を表示できますね。
以上の方法でとりあえず出来ましたけど、
アイキャッチ画像は普通にやってもREST APIで取得出来なくて、
エンドポイントに「?_embed」とかを追加する必要があるんですが、
node-wpapi でのやり方がわからなかったので、
WordPress の function.php を弄って、APIに項目を追加して表示させたりしました。
それについては、また今度ご紹介します。