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 に次のように設定していました。
1 | 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のサイトでもプレビュー画面を実装することができました。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import Client from './Client'; import { Suspense } from 'react'; export default async function Page() { return ( <> <Suspense> {/* @ts-expect-error Server Component */} <Client /> </Suspense> </> ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | "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 ( <> // ここにプレビュー画面の内容を記述 </> ); } |


