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

在Next.js中如何正确使用存储在服务器端的JSON文件?

可行的实现方案

1. 封装服务端数据读取逻辑,复用getStaticProps/getServerSideProps

不用每个页面重复写fs读取代码,把这部分逻辑抽成公共模块,所有需要数据的页面直接调用即可。

比如新建lib/app-data.js文件:

import fs from 'fs/promises';
import path from 'path';

export async function getAppData() {
  // 拼接JSON文件的绝对路径
  const filePath = path.join(process.cwd(), 'data', 'your-data.json');
  const jsonData = await fs.readFile(filePath, 'utf8');
  return JSON.parse(jsonData);
}

然后在需要数据的页面里,直接调用这个函数:

import { getAppData } from '../lib/app-data';

export async function getStaticProps() {
  const appData = await getAppData();
  return {
    props: { appData },
    // 若数据会更新,可加revalidate配置自动重新生成页面
    revalidate: 60 // 每60秒重新验证一次
  };
}

export default function YourPage({ appData }) {
  // 直接使用appData
  return <div>{JSON.stringify(appData)}</div>;
}

这样每个页面只需几行代码就能拿到数据,不用重复编写fs相关逻辑。

2. 用App Router的Server Components直接读取数据(Next.js 13+)

如果用的是App Router,Server Components可以直接在组件内读取文件系统,无需额外的getStaticProps,还能把数据传给客户端组件,完全不会将数据暴露到前端。

比如新建components/ServerDataProvider.jsx Server Component:

import fs from 'fs/promises';
import path from 'path';

export default async function ServerDataProvider({ children }) {
  const filePath = path.join(process.cwd(), 'data', 'your-data.json');
  const jsonData = await fs.readFile(filePath, 'utf8');
  const appData = JSON.parse(jsonData);

  // 把数据通过props传给子组件(客户端组件也能接收)
  return children(appData);
}

然后在页面或布局中使用:

import ServerDataProvider from './components/ServerDataProvider';
import ClientComponent from './components/ClientComponent';

export default async function Home() {
  return (
    <ServerDataProvider>
      {(appData) => <ClientComponent data={appData} />}
    </ServerDataProvider>
  );
}

这种方式下,数据仅在服务端读取,前端根本看不到原始JSON文件的路径或内容,完全符合“只有网站本身使用数据”的需求。

3. 给API路由加访问限制(若必须保留客户端请求)

如果你确实需要在客户端发起请求,得给API路由加保护,防止外部访问。比如在API路由里检查请求来源是否为你的域名,或者用内部密钥验证(注意密钥不能存于前端代码,仅在服务端校验)。

比如pages/api/data.js:

import fs from 'fs/promises';
import path from 'path';

export default async function handler(req, res) {
  // 检查请求是否来自本域
  const origin = req.headers.origin;
  if (origin !== process.env.NEXT_PUBLIC_APP_URL) {
    return res.status(403).json({ message: '无访问权限' });
  }

  const filePath = path.join(process.cwd(), 'data', 'your-data.json');
  const jsonData = await fs.readFile(filePath, 'utf8');
  res.status(200).json(JSON.parse(jsonData));
}

不过这种方式不如前两种安全,域名验证可能被绕过,优先推荐服务端直接读取的方案。

内容的提问来源于stack exchange,提问作者willaayy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 05:15:06