【Next.js】WordPressをヘッドレスCMS化してブログを公開する
WordPressのブログをNext.jsで公開したかったので、WordPressをヘッドレスCMS化しました。
今回はその作業工程を簡単にまとめた内容です。
記事データ管理や管理画面は「WordPress」、フロントエンドは「Next.js」という構成になります。
目次
Next.jsのプロジェクトを作成する
$ npx create-next-app blog # 「blog」部分は自由(アプリケーション名)
WordPressでAPIを作る
1. プラグイン「WP GraphQL」を追加する
「WP GraphQL」のプラグインを追加して有効化します。
2. APIのエンドポイントを確認する
「WP GraphQL」→「Settings」でGraphQLのエンドポイントを確認することができます。Next.jsでデータ取得をする時に使用するのでチェックしておきましょう。
Next.jsで記事データを取得する
1. APIのエンドポイントを.envに記載する
.envファイルに下記を追加します。(https://example.com/
をWordPressのURLに変更してください。)
WORDPRESS_API_URL=https://example.com/graphql
2. 投稿一覧データを取得する
今回は投稿一覧のデータを取得します。下記の関数でWordPressで公開されている投稿データを取得することができます。
その他のデータを取得したい場合は、取得したいデータに合わせてquery
の値を変更してみてください。(「特定の投稿データ」や「カテゴリやタグ」など)
// 「投稿一覧」を取得
export async function getPostsFromWordPress() {
const data = await fetch(`${process.env.WORDPRESS_API_URL}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: `
{
posts {
nodes {
id
slug
status
title
featuredImage {
node {
mediaItemUrl
}
}
date
modified
content
categories {
nodes {
id
name
slug
}
}
tags {
nodes {
id
name
slug
}
}
}
}
}
`,
}),
})
return data.json()
}
Next.jsで記事を表示する
ここまででWordPressからデータを取得してNext.jsで受けることができました。次はこのデータを実際に表示していきます。
import React from 'react';
export default function Home({posts}) {
return (
<div>
{posts.map(post => {
<div>{post.title}</div>
})}
</div>
)
}
export const getStaticProps = async () => {
// ===========================
// 投稿一覧データを取得する
// ===========================
const res_posts = await getPostsFromWordPress();
const posts = res_posts.data.posts.nodes
return {
props: {
posts, // 投稿一覧データ
},
}
}
WordPressからNext.jsにリダイレクトする
何も設定をしない状態だとWordPressとNext.jsのページが重複してしまいます。公開ページを1つに統一するための一つの方法として、WordPress→Next.jsへリダイレクト処理があります。
方法⑴ プラグイン「Headless Mode」を使用する
プラグイン「Headless Mode」を追加します。(プラグインの検索結果で出てきます。)
このプラグインを使用すると、全ての公開ページを一括で新しいドメインへリダイレクト処理してくれます。各ページのURLパスはそのままでドメインだけ変更したい場合はこのプラグインがおすすめです。
FTPソフトを使用してwp-config.php
に下記を追加するだけで設定できます。(https://example.com
の部分はリダイレクト先のURLに変更)
define( 'HEADLESS_MODE_CLIENT_URL', 'https://example.com' );
方法⑵ プラグイン「Redirection」を使用する
プラグイン「Redirection」を追加します。(プラグインの検索結果で出てきます。)
このプラグインを使用すると、ページごとやディレクトリごとのリダイレクト処理をすることができます。新しいサイトでURLパスを一部変えたい場合などはこのプラグインがおすすめです。
Redirectionの設定ページで、「転送元の相対URL」と「リダイレクト先のURL」などをそれぞれ設定することでリダイレクト処理されます。(正規表現を使用するとディレクトリごとの処理なども可能です)
Next.jsでプレビュー機能を作る
何も設定しないとプレビューはWordpress側のページで見ることになってしまいます。そこでプレビューもNext.js側のサイトで確認できるようにしたいです。
ただし作成中や未公開の記事はWPGraphQLでは取得されません。なのでプラグインなどで未公開記事データも取得できるように設定する必要があります。
プラグイン「WPGraphQL JWT Authentication」を追加する
認証機能を利用できるプラグイン「WPGraphQL JWT Authentication」を使用します。
このプラグインでは管理画面の検索結果ではヒットしないので、「WPGraphQL JWT Authentication」のgithubページからzipファイルをダウンロードします。ダウンロードしたzipファイルを管理画面で追加して有効化します。
「wp-config.php」を編集する
FTPソフトを使用してwp-config.php
に下記を追加します。
define( 'GRAPHQL_JWT_AUTH_SECRET_KEY', 'ランダム文字列' );
「.htaccess」を編集する
FTPソフトを使用して.htaccess
に下記を追加します。
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
refresh tokenを発行する
WPGraphQLで下記クエリを実行して「refresh token」を取得します。
(clientMutationIdは「clientMutationId」「password」「username」が同じ場合に毎回同じrefreshTokenを返してくれるという仕様のためにありますが、基本refreshTokenは一度しか発行する必要がないのでなんでもOK)
mutation Login {
login(
input: {
clientMutationId: "適当な文字列1"
password: "WordPressのログインパスワード"
username: "WordPressのログインユーザ名"
}
) {
refreshToken
}
}
.envファイルを編集する
Next.jsの.env
ファイルに下記を追記します。
WORDPRESS_AUTH_REFRESH_TOKEN="取得したrefreshToken"
WORDPRESS_PREVIEW_SECRET="適当な文字列2"
プレビューを表示するページを作成する
下記URLのように/preview
のページに、⑴WORDPRESS_PREVIEW_SECRET
と⑵見たい記事のPOST_ID
をパラメータを持たせると、その記事のプレビューが見れる仕様にしていきます。
(WORDPRESS_PREVIEW_SECRET
を知っている人はプレビューが見れる)
http://localhost:3000/preview?secret=[WORDPRESS_PREVIEW_SECRET]&id=[POST_ID]
プレビューしたい記事のデータを取得するコード例です。
// プレビューしたい「投稿データ」を取得
export async function getPreviewPostFromWordPressByPostId(id) {
const data = await fetch(`${process.env.WORDPRESS_API_URL}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
'Authorization': `Bearer ${process.env.WORDPRESS_AUTH_REFRESH_TOKEN}`,
},
body: JSON.stringify({
query: `
{
postBy(postId: ${Number(id)}) {
title
content
// ...省略
}
}
`,
}),
})
return data.json()
}
プレビューページ(/preview
)に取得した記事データを反映します。
import React from 'react';
export default function Preview({post}) {
return (
<div>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{__html: post.content}}></div>
</div>
)
}
export const getServerSideProps = async ({query}) => {
const {secret, id} = query
// ===========================
// プレビュー投稿データを取得する
// ===========================
const res_post = await getPreviewPostFromWordPressByPostId(id)
const post = res_post.data.postBy
return {
props: {
post, // 投稿一覧データ
},
}
}
編集画面プレビューのリンク先を変更する
WordPress管理画面の「投稿一覧」や「編集ページ」にあるプレビューボタンのリンク先を新サイトのプレビューページURLに変更します。
WordPressのテーマエディタにあるfunctions.php
に下記コードを追加してください。
「クラシックエディタ」の場合
/**
* redirect to custom preview link
*/
function preview_link($link) {
global $post;
$secret = 'ここに.envファイルのWORDPRESS_PREVIEW_SECRET';
$new_link = 'http://localhost:3000/api/preview?secret='.$secret.'&id='.$post->ID;
return $new_link;
}
add_filter('preview_post_link', 'preview_link');
「ブロックエディタ」の場合
/**
* Gutenbergによる投稿プレビューのURL(プレビュー生成中からのリダイレクト先)を変更する
* WordPress 5.3.2で動作確認
* @param $response
* @return array
*/
function my_rest_pre_echo_response($response) {
global $post;
$secret = 'ここに.envファイルのWORDPRESS_PREVIEW_SECRET';
$new_link = 'http://localhost:3000/api/preview?secret='.$secret.'&id='.$post->ID;
if(!is_user_logged_in())
return;
if($response['status'] === 'draft'){
$response['link'] = $new_link;
}
return $response;
}
add_filter( 'rest_pre_echo_response', 'my_rest_pre_echo_response', 100 );
まとめ
microCMSなど、他のヘッドレスCMSにも興味があるのでいつか触ってみたいと思います。