Next.js App RouterでmicroCMSの画面プレビューに対応する
microCMSのテンプレート作成に挑戦する中で、画面プレビューの実装を行いました。Next.js App Routerを使用してmicroCMSのプレビュー機能を実装する方法を紹介します。ngrokを使用してローカルのNext.jsアプリに中継するためのセットアップ方法も紹介されています。microCMSのAPI設定画面でngrokのURLを設定し、Next.js側では公開済みのコンテンツを表示するページを用意する必要があります。また、プレビューコンテンツの取得にはdraft_keyを利用します。
目次
microCMSのテンプレート作成に挑戦する中で、画面プレビューをはじめて実装しました。
今回はNext.js App RouterでmicroCMSのプレビュー機能を実装する方法を簡単に紹介します。
ngrokでローカルのNext.jsにプロキシーする
Next.jsアプリのセットアップ方法については割愛します。
ローカルでこの機能を開発するには、microCMSから送信されるWebhookイベントを、ローカルのNext.jsアプリに中継する必要があります。
今回はngrokを利用して、リクエストを中継します。
npm run dev
ngrok http 3000
URLが発行されましたので、コピーしましょう。
Session Status online
Account John due (Plan: Free)
Update update complete, restart for new version!
Version 3.1.0
Region Japan (jp)
Latency 25ms
Web Interface http://127.0.0.1:4040
Forwarding https://xxxx-xxxx-xxxx-xxxx.ngrok-free.app -> http://localhost:3000
microCMSで、ngrokのURLを設定する
ngrokで発行されたURLを、microCMSのプレビューURLに設定しましょう。
[API設定画面]の[画面プレビュー]を開き、[遷移先URL]にURLを入れます。
/app/products/[content_id]/page.tsx
に遷移させたい場合、https://xxx-xxx-xxx-xxx.ngrok-free.app/products/{CONTENT_ID}?draft_key={DRAFT_KEY}
のように設定します。
[画面プレビューボタンの表示]をオンにして保存しましょう。
App Routerで公開済みのコンテンツを表示するページを用意
続いてNext.js側にページを用意します。まずはmicroCMSのJS SDKセットアップと、記事取得処理のラッパー関数を用意します。
import { createClient } from 'microcms-js-sdk'
import type { MicroCMSListContent, MicroCMSQueries } from 'microcms-js-sdk'
if (!process.env.MICROCMS_SERVICE_DOMAIN) {
throw new Error('MICROCMS_SERVICE_DOMAIN is required')
}
if (!process.env.MICROCMS_API_KEY) {
throw new Error('MICROCMS_API_KEY is required')
}
export const client = createClient({
serviceDomain: process.env.MICROCMS_SERVICE_DOMAIN,
apiKey: process.env.MICROCMS_API_KEY,
})
export const getProductById = async (id: string, queries: MicroCMSQueries = {}) => {
return client.get<MicroCMSListContent>({
endpoint: 'products',
contentId: id,
queries,
})
}
続いてページを用意しましょう。
app/product/[content_id]/page.tsx
を、次のように実装します。
import { getProductById } from '@/app/libs/microcms'
import { notFound } from 'next/navigation'
type PageProps = {
params: {
id: string
}
}
export default async function Product({ params: { id: productId } }: PageProps) {
const product = await getProductById(productId).catch(() => null)
if (!product) {
notFound()
}
return <pre><code>{JSON.stringify(product, null, 2)}</code></pre>
}
今回は、あくまでデータ取得だけにフォーカスするため、JSONデータをそのまま出力させます。
App RouterでmicroCMSのプレビューコンテンツを取得できるようにする
先ほどのコードは、まだ画面プレビューに対応していません。
次のコードに変更して、microCMSから送信されるdraft_key
を利用したプレビュー記事の取得に対応しましょう。
import { getProductById } from '@/app/libs/microcms'
import { notFound } from 'next/navigation'
type PageProps = {
params: {
id: string
}
searchParams: {
draft_key?: string
}
}
export default async function Product({ params: { id: productId }, searchParams }: PageProps) {
let product = await getProductById(productId).catch(() => null)
if (!product) {
const draftKey = searchParams?.draft_key || null
if (draftKey) {
product = await getProductById(productId, {
draftKey
}).catch(() => null)
}
}
if (!product) {
notFound()
}
return <pre><code>{JSON.stringify(product, null, 2)}</code></pre>
}
「公開ずみのページ」と「下書きプレビュー」を同じファイルで処理するため、すこし乱暴ですが、APIを2回叩く実装にしています。
公開記事として取得できなかった場合は、下書きを取得するイメージですね。
もしかすると、draft_key
の有無で呼び出し方を変えても良いかもしれません。
動作確認
準備ができたので、実際にアクセスしてみましょう。
新しく記事を作ると、[画面プレビュー]ボタンが表示されます。これをクリックしましょう。
エラーにならず、記事内容が表示されました。
デプロイ後にURLを変更しよう
ngrokのままではいろいろ不便なので、デプロイ後は切り替えておきましょう。
もしより安全に運用したい場合は、searchParams.draft_key
がある場合は認証を通すmiddlewareとかを用意するとよいかもしれません。