You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 20:50:31