Next.js × microCMS でSSGサイトを構築する
今回はNext.jsとmicroCMSでSSGサイトを構築したとき、必要だった設定をまとめます。
結論から言うと、以下の3点を押さえる必要がありました。
- 静的エクスポートを有効化する
- 動的ページにgenerateStaticParams()を追加する
- プレビューはクライアント側でデータを取得する
それぞれ詳しくみていきます。
静的エクスポートを有効化する
next.config.js に 下記の記述を追加します。
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 に最適化オフを設定します。
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() はこんな感じです。
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)はページがある場合にパスを生成するようにします。
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サイトでプレビュー画面を実装する


