今回はNext.jsとmicroCMSでSSGサイトを構築したとき、必要だった設定をまとめます。
結論から言うと、以下の3点を押さえる必要がありました。
- 静的エクスポートを有効化する
- 動的ページにgenerateStaticParams()を追加する
- プレビューはクライアント側でデータを取得する
それぞれ詳しくみていきます。
静的エクスポートを有効化する
next.config.js に 下記の記述を追加します。
1 2 3 | const nextConfig = { output: 'export', }; |
しかし、この記述を追加すると以下のエラーが発生しました。
Unhandled Runtime Error
Error: Image Optimization using the default loader is not compatible with { output: 'export' }.
Possible solutions:
– Remove { output: 'export' } and run “next start” to run server mode including the Image Optimization API.
– Configure { images: { unoptimized: true } } in next.config.js to disable the Image Optimization API.
Read more: https://nextjs.org/docs/messages/export-image-api
output: ‘export’を利用する場合は画像最適化を無効化する必要があるようです。
next.config.js に最適化オフを設定します。
1 2 3 4 5 6 | const nextConfig = { output: 'export', images: { unoptimized: true, // これを追加 }, }; |
unoptimizedがtrueの場合、画像はサイズやフォーマットを変更しないでそのまま適用されます。
そのためビルド前に画像を事前に最適化しておく必要があるので、注意してください。
これで「npm run build」で /out 配下に静的ファイルが出力されるようになります。
動的ページにgenerateStaticParams()を追加する
「/blog/[slug]」のような動的ルートも、SSGではビルド時に静的ファイルとして生成しておく必要があります。
そのときに使う関数がgenerateStaticParams()です。
この関数は簡単に言うと、どのURL作るかをNext.jsに渡す関数です。
たとえばブログ詳細ページ「/blog/[slug]」の[slug]に入る値を事前に用意して渡すことで、ビルド時に静的なページが生成されます。
またmicroCMSの一覧取得は1リクエスト最大100件までです。
そこでgenerateStaticParams() でもlimit + offsetでページングしながら全件を集める必要があります。
たとえば記事詳細(/blog/[slug]/page.tsx)の generateStaticParams() はこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import { getBlogList } from '@/app/_libs/microcms'; export async function generateStaticParams() { // limit を最大値に設定 const queries = { fields: "id", limit: 100 }; // 全記事を格納する配列 let allArticles: { id: string }[] = []; let offset = 0; while (true) { // APIリクエストで記事を取得 const articlesListResponse = await getBlogList({ ...queries, offset }); const { contents: articles } = articlesListResponse; // 取得データが空の場合終了 if (!articles || articles.length === 0) { break; } // 記事を配列に追加 allArticles = [...allArticles, ...articles]; // 最後のページに到達 if (articles.length < 100) { break; } // 次のページへ offset += 100; } // 記事IDからパスを生成 const paths = allArticles.map((article) => ({ slug: article.id, })); return paths; } |
一覧ページ(/blog/page.tsx)は固定パスのためgenerateStaticParamsは不要です。
一覧のページ送り(/blog/p/[current]/page.tsx)はページがある場合にパスを生成するようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { getBlogList } from '@/app/_libs/microcms'; export async function generateStaticParams() { const paths = []; const data = await getBlogList({ // 一覧ページの1ページあたりの記事数 limit: 10, }); // APIレスポンスの totalCount から総ページ数を計算 const totalPages = Math.ceil(data.totalCount / 10); // 総ページ数ぶんだけパスを生成 for (let page = 1; page <= totalPages; page++) { paths.push({ current: page.toString() }); } return paths; } |
プレビューはクライアント側でデータを取得する
microCMSでプレビューを実装する場合、「draftKey」を使って記事の取得します。
しかし、ビルド時にデータを取得しようとするとエラーになってしまいます。
そこで、プレビュー専用ページは固定パスにして、データ取得処理はクライアントコンポーネント側に移しました。
詳細は下記の記事にまとめています。参考にしてみてください。
Next.js × microCMSのSSGサイトでプレビュー画面を実装する


