Next.js搭配next-i18next时GetStaticProps的revalidate失效
问题描述
使用next-i18next提供的serverSideTranslations方法时,Next.js ISR(增量静态再生成)的revalidate机制无法正常运行,相关复现代码如下。
新用户注册时,系统会为每种支持的语言生成对应的静态页面,支持的语言包括:da(默认语言)、en、sv、de。
项目部署在Vercel平台时,构建阶段已经预生成的页面可以正常运行,下方代码无异常;但新用户注册后,对应页面无法触发重新验证,会抛出500内部服务器错误,提示页面未生成。
具体问题位置可参考代码注释:
export async function getStaticPaths({ locales }) { const { data: profiles, error } = await supabase.from("profiles").select("*"); console.log(locales); const paths = profiles .map((profile) => locales.map((locale) => ({ params: { profileName: profile.username }, locale, // 在此处传入locale })) ) .flat(); console.log(paths); return { paths, fallback: "blocking" }; } export async function getStaticProps({ params, locale }) { const { data: profiles, error } = await supabase .from("profiles") .select("*") .eq("username", params.profileName) .single(); return { props: { profiles, ...(await serverSideTranslations(locale, ["Profil"])), // 移除该行时所有功能正常,添加该行后GetStaticPaths和GetStaticProps运行异常 }, revalidate: 30, }; }
问题根因
该问题和revalidate本身逻辑无关,是serverSideTranslations在ISR动态生成页面的Serverless运行时环境中执行抛错,直接中断了静态页面生成流程,最终返回500错误,常见触发原因有两个:
- next-i18next的翻译文件路径配置使用了相对路径,Vercel部署时Serverless Function的工作目录和本地开发环境不一致,运行时找不到对应语言的翻译文件直接抛错
- 首次访问未预生成的多语言路径时,偶发
locale参数取值异常(比如取到undefined),serverSideTranslations接收到非法locale参数直接抛出异常
解决方案
- 对齐Next.js和next-i18next的i18n配置,确保两边声明的默认语言、支持语言列表完全一致,避免locale参数匹配异常:
// next.config.js module.exports = { i18n: { defaultLocale: 'da', locales: ['da', 'en', 'sv', 'de'], }, }
- 修正next-i18next配置中的翻译文件路径,使用Node.js绝对路径指向翻译文件目录,保证Vercel运行时可以正确读取文件:
// next-i18next.config.js const path = require('path') module.exports = { i18n: { defaultLocale: 'da', locales: ['da', 'en', 'sv', 'de'], }, localePath: path.resolve('./public/locales'), }
- 给
getStaticProps增加错误兜底和参数校验,避免未捕获异常中断ISR流程:
export async function getStaticProps({ params, locale }) { try { const { data: profiles, error } = await supabase .from("profiles") .select("*") .eq("username", params.profileName) .single(); // 数据查询异常时直接返回404,避免后续逻辑执行出错 if (error || !profiles) { return { notFound: true, revalidate: 30 } } // 兜底locale取值,避免传入非法参数 const activeLocale = locale ?? 'da' const pageTranslations = await serverSideTranslations(activeLocale, ["Profil"]) return { props: { profiles, ...pageTranslations, }, revalidate: 30, }; } catch (err) { console.error('Page generate error:', err) // 运行时出错时设置短重试间隔,避免持续返回500 return { notFound: true, revalidate: 10 } } }
注意:
serverSideTranslations仅适配Pages Router,若使用App Router请勿调用该方法,需要手动初始化i18n实例加载翻译资源。
内容的提问来源于stack exchange,提问作者Charlie Østergaard
相关产品推荐
相关产品推荐

