NuxtとWordPress でプレビュー機能を実装する
フロントエンドエンジニアのハコザキです。
今回は、WordPressをヘッドレスCMSとして利用するにあたり、
プレビュー機能を実装しNuxtで動かしている環境で表示確認を行う方法についてご紹介します!
ブログやお知らせなどの記事を公開する前に確認するプレビュー機能は
私は必ず使っている機能で、コンテンツ管理としては必須の機能だと思います。
今回実装したデモをご紹介します!
通常のWordPressのようなプレビュー機能が使えるようになっております。
はじめに
これまでのプレビュー機能について
今回の機能を実装する前は、以下の流れで公開の流れを行ってました。
エンジニアやローカル環境でNuxtを動かせる人であれば
プレビューはできたのですが、手順が多くかなり手間になっていました。
- WordPress側のAWS AmplifyへのWebhook通知をOFF
→ 記事ステータスの公開をトリガーとして自動デプロイを行う機能 - 該当記事の公開
- ローカル環境を起動して表示確認
- 記事の修正など
- 該当記事の非公開
- WordPress側のAWS AmplifyへのWebhook通知をON
- 該当記事の公開
今回実装したプレビュー機能により、以下の手順になりました。
通常のWordPressでの投稿とほぼ同じ手順になり、かなりシンプルになりました。
- 該当記事の記事ステータスを非公開にして投稿
- プレビューボタンから表示確認
- 該当記事の修正など
- 該当記事の記事ステータスを公開
ヘッドレスCMSの実装例
NewtやmicroCMSなどのヘッドレスCMSでは、
プレビュー機能の実装例が丁寧に紹介されており、実装は比較的シンプルです。
- Newtチュートリアル
– Next.jsのプレビューモードを利用して、プレビュー環境を作成する
→ Nuxtでも同様の方法で実装できそうです
- microCMSチュートリアル
– Preview Modeを使ってコンテンツの下書きプレビューを行う
WordPressはもともとヘッドレスCMS化前提で作られておりません..
そのため、WordPressをヘッドレスCMSとして利用する際のプレビュー機能は、
設定する手順などが少々大変です。
今回は少し苦戦しながらもなんとか実装できましたのでそちらの方法をご紹介します!
概要
前提条件
- Nuxtのバージョンは2で、SSGで動かしている
target: static
が指定されていること - WordPressは5.6、動かしているPHPバージョンは7.4以上
※ アプリケーションパスワードを使用するため
※ 使用するプラグインのPHPの最低バージョンが7.4以上のため
処理の流れ
- WordPress管理画面のプレビューボタンをクリック
- Nuxtへ必要なパラメータを引き継いで遷移
〇〇.jp/?preview=true&id=〇〇
のようなページ - プレビュー用のページで、WordPressのアプリケーションパスワードをヘッダーにつけ、
id
をもとに非公開の記事情報を取得
※ 動的パラメータでなく固定ページで行う理由は、
動的パラメータの場合、nuxt generate時にエラーになるためです
Nuxtのプレビューモード
Nuxt側についてはこちらの機能を使います。
静的生成されたページのURLに ?preview=true
をつけることで、 asyncData
や fetch
を実行できるようになります。
実装
WordPress:プレビューボタン
はじめに、WordPress管理画面の投稿ページ上のプレビューボタンをクリック
→ Nuxt側に遷移するようにします。
遷移する際に記事のIDとpreviewフラグを渡すことで、
Nuxt側に記事IDを渡すことができ、
静的ファイル上でasyncDataで記事の取得を実行することができます。
続いて、設定中のテーマのfunctions.phpに以下を追記します。
add_action("template_redirect", function () {
if (!is_admin() && isset($_GET["preview"]) && $_GET["preview"] == true) {
$id = $_GET["preview_id"] ? $_GET["preview_id"] : $_GET["p"];
$redirect = add_query_arg(
[
"preview" => "true",
"id" => $id,
],
"http://localhost:3000/preview/" // TODO 本番環境でも動作させる場合はドメインを変更
);
wp_redirect($redirect);
}
});
Nuxt:プレビューページの表示
Nuxt側で、プレビューモードが動作するためのプラグインを作成します。
~/src/plugins/preview.js を作成し、以下の記述をします。
export default function ({ query, enablePreview }) {
if (query.preview) {
enablePreview()
}
}
nuxt.config.jsに上記のプラグインを追加します。
※ enablePreviewはクライアントサイドのみ処理されるため、
プラグインはクライアントサイトでのみ実行できるようにします。
...
plugins: [
{ src: '~/plugins/preview.js', mode: 'client' }
]
...
続いて表示画面です。
今回はプレビューの実装例のためかなりシンプルにしてますが、
実際は本番環境で表示する形式に見た目などあわせる必要があります。
<template>
<article>
<h1>{{ article.title }}</h1>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="article.content"></div>
</article>
</template>
<script>
export default {
async asyncData({ app, payload, $axios, params, route, error, $preview }) {
// プレビュー判別
const { id, preview } = route.query
const isPreview = !!preview
// コンテンツ取得
const contents = await axios
.$get(`https://〇〇.com/wp-json/wp/v2/〇〇/${id}?_embed&status=draft`)
if (!contents && !Object.keys(contents).length) {
error({
statusCode: 404,
})
return false
}
// 表示用に整形
const article = {
title: contents.title.rendered,
content: contents.content.rendered,
}
return {
article,
}
},
head: {
meta: [{ hid: 'robots', name: 'robots', content: 'noindex' }],
},
}
</script>
記事取得は以下のエンドポイントを指定します。
https://〇〇.com/wp-json/wp/v2/〇〇/${id}?_embed&status=draft
※ slugでも記事取得は可能ですが、配列で帰ってくることに注意です
基本的な実装の流れはこれでokなのですが、
このままでは記事の取得ができずエラーになると思います。
WP REST APIでは、status=draftをつけることで記事ステータスが
下書きコンテンツ(下書き or 非公開のもの)を取得できます。
ですが、この機能は認証が必要なため通常の取得方法では実行できないようになっています。
WP REST APIの認証について
WP REST APIの認証についてはいくつかありますが、 今回試したものをご紹介します。
- クッキー認証
nonceと呼ばれるトークンをリクエストに付与することで認証必要な機能が実行できますが、
WordPressのクッキーに依存しているため、外部アプリケーション(今回だとNuxt)から実行はできませんでした。
WordPressの内部から使われていて、かつログインしていることが必須となっており、
今回の要件には合いませんでした..
クッキー認証はWordPressのプラグインやテーマ開発向きの認証方法のようです。
- アプリケーションパスワードでの認証
外部のアプリケーションがサイトへの接続を許可するための機能です。
ユーザーのログインパスワードとは別に、アプリケーションパスワードを生成します。
WP REST APIを実行する際、
このアプリケーションパスワードを付与してリクエストすることで、認証が必要な機能も実行できるようになります。
今回はアプリケーションパスワードを使うことで、下書き記事の取得までできそうです。
注意点としては、アプリケーションパスワードを使う際
最小限の権限でユーザー設定をする必要があります。
※ 万が一漏洩した場合、想定しない機能が実行されるのを防ぐためです。
今回は、
公開・非公開記事の閲覧のみできるユーザーを作成し、
そのユーザーで作成したアプリケーションパスワードをリクエストヘッダーに付与して、
下書き記事を取得します。
WordPress:プレビュー用ユーザーの作成
通常のWordPressユーザーの作成と同様の方法でユーザーを作成します。
権限グループ(管理者や編集者、購読者など)は後々変更するのでどれか一つを選択します。
続いて、作成したユーザーページからアプリケーションパスワードを作成します。
生成されたものは後々必要になるので忘れずにコピーしておきます。
WordPress:プレビュー用権限グループの作成
プレビュー用のユーザーを作成した後は、 プレビュー用の権限グループを作ります。
User Role Editorというプラグインをインストールします。
User Role Editor は ユーザ権限をカスタマイズできるプラグインです。
デフォルトで用意されているグループの他に新たにグループを作成することができるため、
非公開記事の閲覧のみできる権限グループを作成します。
管理画面 → ユーザー → User Role Editor で設定画面が表示されます。
権限グループを追加 から
今回は下書き閲覧用グループ(ID: previewer)を作成しました。
read_private_posts にチェックをつけて、更新します。
read_private_posts … 非公開の投稿の参照
※ 本来であれば 管理者 or 編集者 でしか実行できない権限を、
新たに下書き閲覧用権限にも付与しています。
これでプレビュー用の権限グループは作成完了です。
WordPress:プレビュー用権限の適用
プレビュー用のユーザーに、作成した権限グループを適用します。
ユーザー一覧 → 対象のユーザー詳細で設定画面を開き、
権限グループに先程作成した権限グループを選択します。
以上でWordPress側の設定は完了になります!
Nuxt:リクエスト時にアプリケーションパスワードの付与
Nuxt側に戻り、axiosで記事取得する部分にリクエストヘッダーを付与します。
WP_AUTH_KEY=WordPressユーザー名:アプリケーションパスワード をbase64変換したもの
続いて、記事取得部分でリクエストヘッダーにこちらの値を付与するようにします。
...
export default {
...
async asyncData({ app, payload, $axios, params, route, error, $preview }) {
// プレビュー判別
const { id, preview } = route.query
const isPreview = !!preview
// コンテンツ取得
const detailBlogs = await axios
.$get(`https://〇〇.com/wp-json/wp/v2/〇〇/${id}?_embed&status=draft`, {
headers: {
Authorization: `Basic ${process.env.WP_AUTH_KEY}`,
},
})
// 表示用に整形
const article = {
title: detailBlogs.title.rendered,
content: detailBlogs.content.rendered,
}
return {
article,
}
},
...
}
...
これで実装は完了です。
ローカル環境で、yarn generate
から yarn start
をして起動しておきます。
WordPreeの投稿画面からプレビューボタンをクリックすると
以下のようにプレビュー表示できればokです!
今回はNuxt × WordPressでプレビュー機能を実装する方法について紹介しました。
通常のWordPressであれば、プレビュー機能をそのまま使うことで良いのですが、
JamstackなサイトでWordPressをヘッドレスCMSとして扱う場合は少し工夫が必要です。
WordPressのサイトを、WP REST API × Nuxt という構成に移行する例はよくありますが、
プレビュー機能について言及・解説している記事がなかったので今回実装してみました!
WordPressをヘッドレスCMSとして扱う事自体少し特殊な事例ではありますが、
参考になればと思います!