Next.js(App Router)でWordPressのプレビュー機能を実装する

Next.js(App Router)でWordPressのプレビュー機能を実装する

Next.js(App Router)でWordPressのプレビュー機能を実装する方法を解説します。

Page RouterにはPreview Modeがありましたが、App RouterではDraft Modeに変更されています。

Draft ModeはPage RouterのPreview Modeと同じく静的レンダリングを動的レンダリングに変える機能を提供してくれます。

ただ、App Routerでは静的レンダリンでは動的レンダリングが採用されるケースが多そうなので、Draft Modeは利用せずに動的レンダリングであること前提に解説を行います。

WordPressから下書きを取得

今回はWordPressの下書き情報はアプリケーションパスワード認証を通して取得を行います。

クッキー認証はプレビュー画面とWordPress管理画面が同一ドメイン上にある場合にしか利用できませんがセキュリティ強度は高いです。

今回利用するアプリケーションパスワード認証ではキーさえ用意すれば下書き情報の取得が可能になります。

以下のようにリクエストパラメーターに &status=draft を含めてヘッダーに Authorization: `Basic ${process.env.PREVIEW_KEY} を含めてリクエストするだけで下書き情報が取得できます。

const res = await fetch(`${process.env.API_URL}wp-json/wp/v2/posts/${slug}?_embed&status=draft`,
  {
    next: {
      revalidate: 10,
    },
    headers: {
      Authorization: `Basic ${process.env.PREVIEW_KEY}`,
    },
  },
);
アプリケーションパスワード認証以外の認証方法
以前、Next.js(Page Router)のプレビューをクッキー認証で表示する方法を解説していますので、クッキー認証の情報が必要な方はそちらを参考にしてください。。

headless WordPressを利用したNext.jsのプレビューをVercelを使わずに実現する – to-R Media

プレビュー用の権限とユーザーを作成

アプリケーションパスワードは通常のWordPressユーザーと同じように作成しますが必要最小限の権限のみをあたえておくと良いでしょう。

デフォルトの権限グループですと「編集者」以上の権限が必要なのでちょっとできることが多いです。

User Role EditorというWordPressプラグインを利用すれば独自の権限グループが作成可能なので、これでプレビュー用の権限グループを作成しておきます。

User Role Editorをインストールするとユーザー一覧に権限グループが作成画面が追加されますのでここでpreviewなどの名前で「read」と「read_private_posts」のみを許可した権限グループを作成します。(利用しているプラグインや参照している情報によってはこれ以上の権限が必要なります。うまく動かない場合は「編集者」から不要そうな権限を外して試すとよいでしょう)

権限グループの作成が終了したらユーザーを作成して権限グループに先ほど作成したpreviewの権限を指定します。

アプリケーションパスワードの作成

ユーザー画面の下部にある「新しいアプリケーションパスワード名」に適当な名前を入力して「新しいアプリケーションパスワードを追加」ボタンからアプリケーションパスワードを作成します。

作成したアプリケーションパスワードはそのままでは利用できません。

「アプリケーションパスワード名:アプリケーションパスワード」と結合した文字列をbase64変換したものを利用します。

base64変換はコマンドラインをなどから簡単にできますので

echo previewpass:M61r z0fV siPU bSn1 9brn SADg | base64

変換したものを .env などに指定しておきましょう。

PREVIEW_KEY=cHJldmlld3Bhc3M6TTYxciB6MGZWIHNpUFUgYlNuMSA5YnJuIFNBRGcK

編集画面にプレビュー画面へのリンクを

to-R Mediaの記事詳細のURLは https://www.to-r.net/media/next-app-router-wordpress/ のようになっています。

プレビューURLはhttps://www.to-r.net/media/[記事id]/?status=draftとなるようにしましょう。

今回の方法ではURLと記事IDが分かれば誰でも下書きが見えてしまいます。Basic認証などの認証方法も合わせて利用するとより安全な運用が可能になります。
参考:Cloudflare Pages Functionsで特定のパラメータがある場合にのみBasic認証を掛ける

その場合は function.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 = "https://www.to-r.net/media/" . $id . "/?status=draft";
    wp_redirect($redirect);
  }
});

WordPress編集画面のプレビューボタンからプレビューURLに転送されるようになります。

Rest APIではあくまで下書き保存した記事データしか取得できません。公開記事を編集途中に確認したいなどの用途には向きませんので注意してください。

Next側にプレビューを設置

Next.jsでは searchParamsstatus=draft がある場合はプレビュー情報をない場合は通常の情報を読みに行きます。

以下のサンプルではgetArticle関数内でsearchParamsによってリクエスト先を変えてArticleを返す実装を行っています。

export const getArticle = async ({
  slug,
  status,
}: {
  slug: string;
  status?: string;
}) => {
  // プレビュー用の記事
  if (status === 'draft') {
    const res = await fetch(
      `${process.env.API_URL}wp-json/wp/v2/posts/${slug}?_embed&status=draft`,
      {
        next: {
          revalidate: 10,
        },
        headers: {
          Authorization: `Basic ${process.env.PREVIEW_KEY}`,
        },
      },
    );
    const article = await res.json();
    return {
      article,
    };
  }

  // 通常の記事
  const res = await fetch(
    `${process.env.API_URL}wp-json/wp/v2/posts/${slug}?_embed`,
    {
      next: {
        revalidate: 10,
      },
    },
  );
  const article = await res.json();
  return {
    article,
  };
};

export default async function Page({ params, searchParams }: Props) {
  const { article } = await getArticle({
    slug: params.slug,
    status: searchParams?.status,
  });
  ....
}

これでNext.js(App Router)でWordPressのプレビュー機能を実装する方法は完成です。

Page RouterでSSGを行っていた頃と比較するとだいぶ手軽にできるようになっているので試してみてください。