Next.jsのgenerateSitemaps
関数を使って複数の動的なサイトマップを実装したサイトにおいて、ビルド時にエラーが生じたのでその解決策を紹介します。
バージョン情報
- Next.js:15.3.1
サイトマップの実装
Multipleなサイトマップを生成するために以下のように実装しました。
// APIリクエストの実行関数
export async function getAllProducts() {
const response = await fetch(`${process.env.NEXT_PUBLIC_PREFIX}${process.env.NEXT_PUBLIC_HOST}/api/product/all`);
const data = await response.json();
const joblist = data.data;
return joblist;
}
export async function generateSitemaps() {
// Fetch the total number of products and calculate the number of sitemaps needed
return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }]
}
export default async function sitemap({
id,
}: {
id: number
}): Promise<MetadataRoute.Sitemap> {
const start = id * 10000
const end = start + 10000
const products = await getAllProducts();
return products.map((product) => ({
url: `${process.env.NEXT_PUBLIC_PREFIX}${process.env.NEXT_PUBLIC_HOST}/product/${product.id}`,
lastModified: product.date,
}))
}
NEXT_PUBLIC_PREFIX
とNEXT_PUBLIC_HOST
は.envファイルで設定している環境変数で、それぞれURLのプレフィクス(https://
またはhttps://
)とホストを示します。
エラー内容
ビルドコマンドを実行してビルドすると、以下のエラーが発生しました。
Error occurred prerendering page "/product/sitemap/sitemap/0.xml".
SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>) at parseJSONFromByte
原因
エラーログから、JSON.parse
が期待しているJSON形式のデータではなく、HTMLやその他の形式のデータを受け取ってしまっている事象が発生していることがわかります。
ここで原因として考えられるのは、process.env.NEXT_PUBLIC_PREFIX
やprocess.env.NEXT_PUBLIC_HOST
が正しく設定されておらず、無効なURLにリクエストを送信している可能性です。
解決方法
そこで、ホストのURLが正しく設定されてAPIリクエストが送られるように、APIリクエスト実行関数周りの実装を以下のように修正しました。
app/product/sitemap.ts
import { headers } from 'next/headers';
export async function getAllJobs(host: string) {
const response = await fetch(`${process.env.NEXT_PUBLIC_API_PREFIX}${host}/api/job/all`);
const data = await response.json();
const joblist = data.data;
return joblist;
}
...
export default async function sitemap({
id,
}: {
id: number
}): Promise<MetadataRoute.Sitemap> {
const start = id * 10000
const end = start + 10000
// ホストの取得
const host = headers().get('host');
// 取得したホストをリクエストのURLに使用する
const products = await getAllJobs(host ?? `${process.env.NEXT_PUBLIC_API_HOST}`);
return products.map((product) => ({
url: `${process.env.NEXT_PUBLIC_PREFIX}${host}/product/${product.id}`,
lastModified: product.date,
}))
}
この修正では、
const host = headers().get('host');
によってリクエストヘッダからホストを取得するようにしました。
これにより上記のエラーが解消し、ビルドが成功するようになりました。

コメント