ISR stopped working after introducing next-intl
There was a clear explanation on the official site, but I completely overlooked it—so here's a quick note for future reference.
How to support Static Rendering with next-intl
There are two ways to do this:
- Handle all pages via a Layout
- Handle each page individually
In most cases, option 1 should suffice.
Using Layout to support all pages
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 } = params;
if (!hasLocale(routing.locales, locale)) {
notFound();
}
// Enable static rendering
setRequestLocale(locale);
return (
// ...
);
}
This is the recommended approach. However, if the associated page has additional dynamic parameters—such as in /[locale]/blog/[slug]
—you’ll need to define generateStaticParams
accordingly.
Using Page-level configuration
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 (
// ...
);
}
This is probably less common, but works fine for isolated cases.
You can also verify that ISR is configured properly in your local environment:
npm run build
npm run start
curl -I http://localhost:3000/hoge
If the Cache-Control
header includes s-maxage
with the same value as your revalidate
setting, you're good to go.
Note: Due to Vercel's infrastructure, s-maxage
is not exposed via curl
when targeting a deployed URL—so don’t expect to see it in production.
In summary, even after introducing next-intl
, as long as static rendering is properly configured via Layout or Page and the revalidation behavior is understood, ISR works just fine—which is reassuring.