NextJS 如何预渲染站点共享导航栏与页脚组件?
NextJS 共享导航栏/页脚的多语言数据获取方案
针对你遇到的共享组件(导航栏、页脚)无法通过页面getServerSideProps获取JSON数据的问题,以下是当前版本(未支持_app.js静态Props)的可行解决方案:
方案1:构建时导入JSON(静态生成场景)
如果JSON数据变更频率低,可直接在_app.js中导入JSON文件,通过上下文传递给共享组件,构建时将数据打包进应用。
修改_app.js:
import { createContext } from 'react'; // 导入多语言JSON文件 import navZhData from '../public/data/nav-zh.json'; import navEnData from '../public/data/nav-en.json'; import footerZhData from '../public/data/footer-zh.json'; import footerEnData from '../public/data/footer-en.json'; const AppContext = createContext(); export default function MyApp({ Component, pageProps }) { // 根据当前语言选择对应数据(可从pageProps或路由参数获取locale) const locale = pageProps.locale || 'zh'; const navData = locale === 'en' ? navEnData : navZhData; const footerData = locale === 'en' ? footerEnData : footerZhData; return ( <AppContext.Provider value={{ navData, footerData }}> <AppWrapper> <Component {...pageProps} /> </AppWrapper> </AppContext.Provider> ); }
导航栏组件中使用上下文:
import { useContext } from 'react'; import { AppContext } from '../_app'; const NavBar = () => { const { navData } = useContext(AppContext); return ( <nav> {navData.items.map(item => ( <a key={item.id} href={item.url}>{item.label}</a> ))} </nav> ); };
此方案性能最优,数据更新时重新构建部署即可。
方案2:通过_app.js的getInitialProps动态获取(服务端渲染场景)
若需实时获取最新数据(比如每次请求都读取最新JSON或从API拉取),可使用_app.js的getInitialProps方法,在应用层面统一获取数据后传递给上下文。
修改_app.js:
import { createContext } from 'react'; import fs from 'fs'; import path from 'path'; const AppContext = createContext(); export default function MyApp({ Component, pageProps, navData, footerData }) { return ( <AppContext.Provider value={{ navData, footerData }}> <AppWrapper> <Component {...pageProps} /> </AppWrapper> </AppContext.Provider> ); } MyApp.getInitialProps = async (appContext) => { // 获取页面原有props const appProps = await App.getInitialProps(appContext); // 从请求上下文获取当前语言(可根据实际路由/i18n方案调整) const locale = appContext.ctx.locale || 'zh'; // 读取本地JSON文件,也可替换为API请求(如fetch) const jsonDir = path.join(process.cwd(), 'public/data'); const navData = JSON.parse(fs.readFileSync(path.join(jsonDir, `nav-${locale}.json`), 'utf8')); const footerData = JSON.parse(fs.readFileSync(path.join(jsonDir, `footer-${locale}.json`), 'utf8')); return { ...appProps, navData, footerData }; };
注意:此方法会使所有页面变为服务端渲染,失去静态生成优化,适合需要实时数据的场景。
方案3:组件内客户端动态获取(兼容静态生成)
如果可以接受客户端加载数据,可在导航栏/页脚组件内用useEffect拉取JSON,不影响页面的静态生成,但会有短暂加载状态。
导航栏组件示例:
import { useState, useEffect } from 'react'; const NavBar = () => { const [navData, setNavData] = useState(null); const locale = 'zh'; // 从上下文或路由获取当前语言 useEffect(() => { const fetchNavData = async () => { const res = await fetch(`/data/nav-${locale}.json`); const data = await res.json(); setNavData(data); }; fetchNavData(); }, [locale]); if (!navData) return <div>加载中...</div>; return ( <nav> {navData.items.map(item => ( <a key={item.id} href={item.url}>{item.label}</a> ))} </nav> ); };
方案选择建议
- 数据变更不频繁:优先选方案1,性能最优。
- 需要实时最新数据:选方案2,但牺牲静态优化。
- 需兼容静态生成且可接受客户端加载:选方案3。
内容的提问来源于stack exchange,提问作者nata
相关产品推荐
相关产品推荐

