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とかを用意するとよいかもしれません。

    関連記事

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark