next-intlを導入したらISRが動かなくなった
2025-08-03
公式サイト にめちゃくちゃ記述がありました。
とはいえめちゃくちゃ見落としていたので、以下備忘録がてら。
next-intl を導入してかつ Static rendering に対応する方法
以下のいずれかとなります。
- Layout で全ページに対応する
- Page で各ページに対応する
基本は 1 で良いっぽいです。
Layout で全ページに対応する
import { setRequestLocale } from 'next-intl/server';
import { hasLocale } from 'next-intl';
import { notFound } from 'next/navigation';
import { routing } from '@/i18n/routing';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}
export default async function LocaleLayout({children, params}) {
const { locale } = await params;
if (!hasLocale(routing.locales, locale)) {
notFound();
}
// Enable static rendering
setRequestLocale(locale);
return (
// ...
);
}
基本はこれで良いっぽいですが、紐づくページにおいて、locale 以外のパラメーターが存在する場合、必要に応じて generateStaticParams を呼び出しましょう。
例: /[locale]/blog/[slug]
のように slug
を持つ場合など
Page で各ページに対応する
import { use } from 'react';
import { setRequestLocale } from 'next-intl/server';
import { useTranslations } from 'next-intl';
import { routing } from '@/i18n/routing';
export const revalidate = 86400;
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}
export default function IndexPage({params}) {
const { locale } = use(params);
// Enable static rendering
setRequestLocale(locale);
// Once the request locale is set, you
// can call hooks from `next-intl`
const t = useTranslations('IndexPage');
return (
// ...
);
}
比較的レアケースな気がします。
またローカルで ISR が正しく設定されているか確認もできます。
npm run build
npm run start
curl -I http://localhost:3000/hoge
curl の結果に Cache-Control が存在するはずなので、s-maxage に revalidate で設定した値が表示されていたらオッケーです。
ちなみに Vercel の仕様で、Vercel 環境に対して curl を叩いても s-maxage は確認できないので注意が必要です。
next-intl を導入した状態でも、Layout や Page での静的対応と、再検証の確認手順を理解しておけば、ISR は問題なく動作することがわかって安心しました。