next-i18next serverSideTranslations致NextJS路由切换时_app.js重渲染闪烁
问题描述
在Next.js中使用getServerSideProps传递serverSideTranslations返回的数据到props时,切换路由会导致_app.js重渲染,出现页面闪烁(白屏);不传递该数据则一切正常。此问题在生产、开发环境均会出现。
相关代码
页面组件代码
export async function getServerSideProps({ locale }) { const data = await serverSideTranslations(locale, ['apple', 'home']); return { props: data, }; } export default function IndexPage() { return <h1>Hi!</h1> }
next-i18next.config.js
module.exports = { i18n: { defaultLocale: 'fr', locales: ['fr', 'en'], }, reloadOnPrerender: process.env.NODE_ENV === 'development', };
next.config.js
const { i18n } = require('./next-i18next.config'); /** @type {import('next').NextConfig} */ const nextConfig = { i18n, reactStrictMode: true, swcMinify: true, poweredByHeader: false, async rewrites() { return [ { source: '/api/:path*', destination: 'http://localhost:8080/:path*', }, ]; }, }; module.exports = nextConfig;
解决方法
1. 统一在_app.js中处理翻译数据
把serverSideTranslations的调用移到_app.js的getServerSideProps里,让所有页面共享翻译数据,避免每个页面单独获取导致_app重复重渲染:
// pages/_app.js import { appWithTranslation } from 'next-i18next'; import nextI18NextConfig from '../next-i18next.config'; function MyApp({ Component, pageProps }) { return <Component {...pageProps} />; } export async function getServerSideProps({ locale }) { const translationProps = await serverSideTranslations( locale, ['apple', 'home'], // 可添加所有页面需用到的命名空间,后续也可按需扩展 nextI18NextConfig ); return { props: { ...translationProps, }, }; } export default appWithTranslation(MyApp);
之后页面组件无需再写自己的getServerSideProps获取翻译,直接用useTranslation钩子即可:
// 页面组件 import { useTranslation } from 'next-i18next'; export default function IndexPage() { const { t } = useTranslation('home'); return <h1>{t('hi')}</h1>; }
2. 启用翻译数据客户端缓存
在next-i18next.config.js中配置缓存选项,让翻译数据在客户端缓存,减少重复请求和渲染:
module.exports = { i18n: { defaultLocale: 'fr', locales: ['fr', 'en'], }, reloadOnPrerender: process.env.NODE_ENV === 'development', localePath: typeof window === 'undefined' ? require('path').resolve('./public/locales') : '/locales', cache: { enabled: true, }, };
3. 优化_app.js的重渲染逻辑
- 用
React.memo包裹MyApp组件,避免无意义的重渲染:
import React from 'react'; import { appWithTranslation } from 'next-i18next'; const MyApp = React.memo(({ Component, pageProps }) => { return <Component {...pageProps} />; }); // ... 其他代码 export default appWithTranslation(MyApp);
- 检查
_app.js中是否有每次渲染都生成新对象/函数的代码,这类不稳定值会触发重渲染。
4. 按需加载翻译命名空间
如果不同页面需要不同的命名空间,可在页面中通过useTranslation按需加载,而非在getServerSideProps中一次性加载所有:
// 页面组件 import { useTranslation } from 'next-i18next'; export default function IndexPage() { const { t, ready } = useTranslation('apple'); if (!ready) return <div>加载中...</div>; // 显示加载占位符,避免白屏闪烁 return <h1>{t('welcome')}</h1>; }
内容的提问来源于stack exchange,提问作者Viktoria
相关产品推荐
相关产品推荐

