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

Next.js App Router下读取JSON文件的问题求助

解决Next.js App Router读取本地JSON文件的问题

核心问题分析

  • 服务端组件用fetch读取本地路径失败:fetch是用于发送HTTP请求的API,无法直接传入本地文件系统路径(如/xxx/project/data/plz.json),服务端环境下这类调用会直接触发fetch failed错误。
  • 客户端组件无限请求:添加'use client'后,组件每次渲染都会执行getData(),且未做请求缓存,导致浏览器反复发起请求(304是缓存命中但仍在重复发起请求)。

解决方案

方案1:服务端组件直接读取文件(推荐)

服务端组件可直接访问文件系统,无需通过fetch,用Node.js的fs模块读取即可:

  1. 将JSON文件放在项目根目录的data文件夹下(无需放在public,服务端读取不需要暴露为静态资源)
  2. 编写读取逻辑:
import fs from 'fs/promises'
import path from 'path'

async function getData() {
  const filePath = path.join(process.cwd(), 'data', 'plz.json')
  const fileContent = await fs.readFile(filePath, 'utf8')
  return JSON.parse(fileContent)
}

export default async function Filter() {
  const plzData = await getData()
  // 后续业务逻辑
  return <div>{/* 渲染内容 */}</div>
}

该方式会在构建或请求阶段读取文件,不会出现重复请求问题。

方案2:客户端组件读取public目录下的JSON

若需在客户端组件中读取,将JSON放在public/data/plz.json,通过fetch请求静态资源URL,同时必须做请求缓存避免无限循环:

用SWR库缓存请求(推荐)

'use client'

import useSWR from 'swr' // 先安装:npm i swr

const fetcher = (url: string) => fetch(url).then(res => res.json())

export default function Filter() {
  const { data: plzData, error } = useSWR('/data/plz.json', fetcher)

  if (error) return <div>加载失败</div>
  if (!plzData) return <div>加载中...</div>

  // 后续业务逻辑
  return <div>{/* 渲染内容 */}</div>
}

手动用useEffect缓存

'use client'

import { useState, useEffect } from 'react'

export default function Filter() {
  const [plzData, setPlzData] = useState<any>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    async function fetchData() {
      try {
        const res = await fetch('/data/plz.json')
        if (!res.ok) throw new Error('请求失败')
        const data = await res.json()
        setPlzData(data)
      } catch (err) {
        setError((err as Error).message)
      }
    }
    fetchData()
  }, []) // 空依赖数组,仅组件挂载时执行一次

  if (error) return <div>{error}</div>
  if (!plzData) return <div>加载中...</div>

  // 后续业务逻辑
  return <div>{/* 渲染内容 */}</div>
}

方案3:静态导入JSON文件

如果JSON内容固定无需动态更新,可直接静态导入:

// 服务端/客户端组件均适用
import plzData from '@/data/plz.json' // 需配置tsconfig路径别名,或用相对路径如'../../data/plz.json'

export default function Filter() {
  // 直接使用plzData
  return <div>{/* 渲染内容 */}</div>
}

该方式会在构建阶段将JSON内容打包进代码,适合内容不常变更的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:22:39