1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

以前の記事で、ブログを作ってみました
記事を公開する前に、実際の画面でどう見えるか確認したかったので「下書きプレビュー」の実装をしてみました

環境について

開発環境は以下の通りです。

  • OS: Windows11 (WSL2)
    • ディストリビューション: Ubuntu 22.04.5 LTS
      • Node.js: 20.19.3
  • インストールしたパッケージ
    • NextJs: 15.3.6
    • microcms-js-sdk: 3.2.0
  • microCMS: 無料プラン

microCMSの準備

下書き記事を用意する

前回作成したブログで、下書きの記事を用意します

blog-draft.png

画面プレビューの設定をする

API設定 > 画面プレビュー を開き、以下のように設定します

遷移先URL

http://localhost:3000/api/draft?slug={CONTENT_ID}&draftKey={DRAFT_KEY}

blog-api-setting.png

これで、microCMSの管理画面にある「画面プレビュー」ボタンを押した際に、CONTENT_IDDRAFT_KEY が付与された状態で Next.js のAPIルートへアクセスされる準備ができました

実装

Next.js の Draft Mode という機能を使用しようと思います

  1. 下書きプレビュー用のエンドポイント(api/draft)を作成
    • Route Handler を作成
  2. 記事ページを修正

Route Handlerの作成

Draft Modeを有効にするためのAPIルート(Route Handler)を作成します
app/api/draft/route.ts を作成し、以下のように記述します

microCMSから送られてくる slug (コンテンツID) と draftKey を受け取り、Draft Modeを有効化してから記事ページへリダイレクトさせます

app/api/draft/route.ts
import { draftMode } from 'next/headers';
import { redirect } from 'next/navigation';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const slug = searchParams.get('slug');
  const draftKey = searchParams.get('draftKey');

  // パラメータが不足している場合は404
  if (!slug || !draftKey) {
    return new Response('Invalid skeleton', { status: 404 });
  }

  // Draft Modeを有効化
  const draft = await draftMode();
  draft.enable();

  // 実際の記事ページへリダイレクト
  // ※ここではブログ詳細ページのパスを /blog/[slug] と仮定しています
  redirect(`/blog/${slug}?draftKey=${draftKey}`);
}

記事ページの修正

記事ページ(例: app/blog/[postId]/page.tsx)を編集して、Draft Modeが有効な場合に下書きデータを取得するようにします

draftMode().isEnabled でDraft Modeの状態を判定できるのがポイントです

app/blog/[postId]/page.tsx
import { client } from "@/libs/client";
import { Blog } from "@/types";
import { draftMode } from "next/headers";
import { notFound } from "next/navigation";

// searchParamsでdraftKeyを受け取る
type Props = {
  params: Promise<{ postId: string }>;
  searchParams: Promise<{ draftKey?: string }>;
};

export default async function BlogPost({ params, searchParams }: Props) {
  const { postId } = await params;
  const { draftKey } = await searchParams;
  
  // Draft Modeが有効かどうかをチェック
  const { isEnabled } = await draftMode();

  // 下書き取得用のオプションを作成
  // Draft Modeが有効かつdraftKeyがある場合のみ queries に draftKey をセット
  const queries = (isEnabled && draftKey) ? { draftKey } : {};

  const blog = await client.getListDetail<Blog>({
    endpoint: 'blogs',
    contentId: postId,
    queries, // ここにdraftKeyが含まれると下書きが取得できる
  }).catch(() => null);

  if (!blog) {
    notFound();
  }

  return (
    <main className="p-4">
      {/* Draft Mode中であることを表示するUIがあると親切 */}
      {isEnabled && (
        <div className="bg-yellow-100 p-2 text-center text-yellow-800 mb-4 rounded">
          現在プレビューモードで閲覧中です
        </div>
      )}
      
      <h1 className="text-3xl font-bold mb-4">{blog.title}</h1>
      <div 
        className="prose"
        dangerouslySetInnerHTML={{ __html: blog.content }} 
      />
    </main>
  );
}

動作確認

  1. 開発サーバーを起動します (npm run dev)
  2. microCMSの管理画面で、記事を「下書き」状態で保存します
  3. 画面右上の「画面プレビュー」ボタンをクリックします

blog-edit.png

別タブが開いて、下書きの内容が表示されれば成功です

blog-preview.png

URLのクエリパラメータに draftKey が付いていることや、APIルートを経由してCookieがセットされていることが確認できると思います

まとめ

Next.js 15の App Router と microCMS で下書きプレビュー機能を実装しました
記事の執筆体験がこれでかなり良くなるので、ぜひ導入してみてください

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?