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

NextJS在getStaticProps中引入fs模块提示Can't resolve 'fs'报错

报错原因

Module not found: Can't resolve 'fs' 是服务端代码被误打包到客户端侧bundle导致的典型错误:

  • fs、path是Node.js原生模块,仅能在服务端环境运行,浏览器环境不存在对应API。
  • 你把这两个模块的导入语句写在了文件顶层,Next.js构建客户端侧JS资源时,会扫描所有顶层导入的依赖并尝试打包,自然找不到只能在Node环境运行的fs模块。
  • 哪怕你只在getStaticProps里使用这些模块,只要是顶层导入,客户端打包逻辑就会尝试解析该依赖,和getStaticProps本身运行在服务端的特性不冲突。
修复方案

核心原则是所有仅能在服务端运行的代码、Node原生模块导入,都不要放在文件顶层,具体修改点如下:

  • 将fs、path这类Node原生模块的导入移到getStaticProps内部,用动态导入的方式加载,Next.js会自动将getStaticProps内的代码从客户端bundle中剔除,不会再被客户端打包逻辑扫描到。
  • 不需要额外配置serverRuntimeConfig获取项目根目录,getStaticProps运行时的工作目录就是项目根目录,直接用process.cwd()即可拿到正确路径,减少多余配置。
  • 补充空值兜底逻辑,避免组件首次渲染时props未注入导致的取值报错。
  • 修正Markdown渲染逻辑:marked.parse返回的是HTML字符串,直接放在JSX中会被转义为纯文本,需要用dangerouslySetInnerHTML才能正常渲染解析后的DOM内容。

修复后的完整代码如下:

import marked from 'marked';
import { useRouter } from 'next/router';

export async function getStaticProps() {
    // 服务端专用模块放在getStaticProps内部动态导入,不会进入客户端打包逻辑
    const fs = (await import('fs')).default;
    const path = (await import('path')).default;
    const projectRoot = process.cwd();

    function getLegalDocument(key: string, locale: string) { 
        const filePath = path.join(projectRoot, './legal', `${key}.${locale}.md`);
        const fileContent = fs.readFileSync(filePath, 'utf8');
        return marked.parse(fileContent);
    }

    const legalDocuments = { 
        legalNotice: {
            de: getLegalDocument('legal_notice', 'de'),
            en: getLegalDocument('legal_notice', 'en'),
            es: getLegalDocument('legal_notice', 'es'),
            fr: getLegalDocument('legal_notice', 'fr'),
            it: getLegalDocument('legal_notice', 'it'),
        },
        privacyPolicy: {
            de: getLegalDocument('privacy_policy', 'de'),
            en: getLegalDocument('privacy_policy', 'en'),
            es: getLegalDocument('privacy_policy', 'es'),
            fr: getLegalDocument('privacy_policy', 'fr'),
            it: getLegalDocument('privacy_policy', 'it'),
        },
        termsOfService: {
            de: getLegalDocument('terms_of_service', 'de'),
            en: getLegalDocument('terms_of_service', 'en'),
            es: getLegalDocument('terms_of_service', 'es'),
            fr: getLegalDocument('terms_of_service', 'fr'),
            it: getLegalDocument('terms_of_service', 'it'),
        }
    }

    return { 
        props: { legalDocuments },
    }
};

type Props = {
    legalDocuments?: Record<string, Record<string, string>>;
    documentType: string;
}

const LegalDocument = ({ legalDocuments, documentType }: Props) => {
    if (!legalDocuments || !legalDocuments[documentType]) {
        return <div>{documentType}</div>
    }

    const languages = legalDocuments[documentType];
    const { locale, defaultLocale } = useRouter();
    const targetContent = languages[locale] || languages[defaultLocale];

    if (!targetContent) {
        return <div>{documentType}</div>
    }

    return <div dangerouslySetInnerHTML={{ __html: targetContent }} />
}

export default LegalDocument
额外说明
  • 如果使用Next.js 11及以上版本,也可以在顶层导入fs,但要确保导入的模块仅在getStaticProps/getServerSideProps这类服务端执行的函数中使用,动态导入的写法兼容性更好,覆盖所有Next.js版本。
  • 不要在客户端组件的顶层导入任何Node原生模块,只要代码可能在浏览器环境运行,就会触发同类报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:33:26