Next.js × microCMSのSSGサイトでプレビュー画面を実装する
microCMS では管理画面からプレビュー用URLを設定し、公開前の記事を実際の見た目で確認できます。
しかし、Next.js + microCMS でプレビュー画面を実装する際、SSG(静的書き出し)設定をしているとビルドが通らないという壁にぶつかりました。
プレビュー画面について
microCMS では、下書き記事でも「プレビュー」表示が可能です。
プレビューを表示するには、まずAPI設定の「遷移先URL」に次のようなURLを設定します。
https://yourdomain.com/blog/preview/{CONTENT_ID}?dk={DRAFT_KEY}
- {DRAFT_KEY} 下書き用のドラフトキー(draftKey)
- {CONTENT_ID} 記事のコンテンツID
この2つを受け取って表示するページをNext.js側に用意すれば、下書きプレビューが実現します。
課題
今回のサイトは全体をSSGで構築するため、Next.js の next.config.js に次のように設定していました。
output: 'export'これはすべてのページを静的に書き出すための設定です。
しかし、この設定を有効にした状態で「app/blog/preview/[slug]/page.tsx」のような動的ルートで「draftKey」を使ってデータ取得をしようとするとビルドエラーになりました。
Error: Page "/blog/preview/[slug]" is missing "generateStaticParams()" so it cannot be used with "output: export" config.
- 「output: 'export'」では、すべてのページがビルド時に静的に生成される必要がある
- いっぽうプレビューは「draftKey」を使って実行時に取得したい(= 静的生成できない)
そのため、ビルドが失敗してしまいました。
動的ルートをやめ、クライアントで取得して解決
これを回避するため、まずルーティングを「/blog/preview」に固定し、「記事ID」や「draftKey」はクエリパラメータ(?slug={CONTENT_ID}&dk={DRAFT_KEY})で受け取る形に変更しました。
https://yourdomain.com/blog/preview?slug={CONTENT_ID}&dk={DRAFT_KEY}
そして、ビルド時ではなくブラウザ側でデータを取得できるように、処理をクライアントコンポーネント(Client.tsx)に移しました。
こうすると「/blog/preview」は静的に1ページとして出力され、表示時にクエリを読んでmicroCMSからデータを取ってきます。
これでSSGのサイトでもプレビュー画面を実装することができました。
import Client from './Client';
import { Suspense } from 'react';
export default async function Page() {
return (
<>
<suspense>
{/* @ts-expect-error Server Component */}
<client>
</client></suspense>
);
}
"use client";
import { getBlogDetail } from '@/app/_libs/microcms';
import { useSearchParams } from 'next/navigation'
export default async function Client() {
const searchParams = useSearchParams();
const dk = searchParams.get('dk') || '';
const slug = searchParams.get('slug') || '';
const data = await getBlogDetail(slug, {
draftKey: dk,
});
return (
<>
// ここにプレビュー画面の内容を記述
);
}


