找不到模块:无法解析 Next.js 应用程序中的 'fs'

Module not found: Can't resolve 'fs' in Next.js application

无法确定我的 next.js 应用中发生了什么。因为fs是nodejs默认的文件系统模块。它给出了 module not found.

的错误

可能是您尝试实现的模块不应该在浏览器中 运行。 IE。它只是服务器端。

fspath 或其他节点本机模块只能在服务器端代码中使用,例如“getServerSide”函数。如果您尝试在客户端中使用它,即使您只是 console.log 它也会出错。console.log 也应该 运行 在服务器端函数中。

当您导入“fs”并在服务器端使用它时,next.js 足够聪明地看到您在服务器端使用它,因此它不会将该导入添加到客户端包中

我使用的一个包给我​​这个错误,我用

解决了这个问题
module.exports = {
 
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback.fs = false
    }

    return config
  },
  
}

但这是在终端上发出警告:

"Critical dependency: require function is used in a way in which

 dependencies cannot be statically extracted"

然后我尝试在浏览器上加载节点模块。我从 node_modules 复制了节点模块的“min.js”并放在“public/js/myPackage.js”中并用脚本加载它

export default function BaseLayout({children}) {
  return (
    <>
      <Script
        // this in public folder
        src="/js/myPackage.js"
        // this means this script will be loaded first
        strategy="beforeInteractive"
      />
    </>
  )
}

此包已附加到 window 对象和 node_modules 源代码的 index.js:

if (typeof window !== "undefined") {
  window.TruffleContract = contract;
}

所以我可以作为 window.TruffleContract 访问此脚本。但这不是一种有效的方法。

帮我清缓存 npm 缓存清理 -f

然后将节点版本更新到最新的稳定版本 (14.17.0) 有效

如果您使用 fs,请确保它仅在 getInitialProps or getServerSideProps 以内。 (任何东西都包括服务器端渲染)。

您可能还需要创建一个包含以下内容的 next.config.js 文件来构建客户端包:

对于webpack4

module.exports = {
  webpack: (config, { isServer }) => {
    // Fixes npm packages that depend on `fs` module
    if (!isServer) {
      config.node = {
        fs: 'empty'
      }
    }

    return config
  }
}

对于webpack5

module.exports = {
  webpack5: true,
  webpack: (config) => {
    config.resolve.fallback = { fs: false };

    return config;
  },
};

注意:对于其他模块如path,可以添加多个参数如

{
  fs: false,
  path: false
}

对我来说,问题是安装了旧版本的node.js。它需要 node.js 版本 14 及更高版本。解决方案是转到 node.js 网页,下载最新版本并安装它。然后重新运行这个项目。全部成功!

我在尝试使用 babel 时遇到了同样的问题。

对我来说这很有效:

#添加一个.babelrc文件到项目的根目录并定义预设和插件 (在我的例子中,我对 babel 的宏有一些问题,所以我定义了它们)

{
    "presets": ["next/babel"],
    "plugins": ["macros"]
}

之后关闭您的服务器并运行再次

我确实遇到了这个问题。我的问题是我正在导入我在 types.d.ts 文件中声明的类型。

我是这样导入的,多亏了 VSCode 提供的自动填充功能。

import {CUSTOM_TYPE} from './types'

本来应该是这样的:

import {CUSTOM_TYPE} from './types.d'

就我而言,我认为 .d 是不必要的,所以我最终将其完全删除并将我的文件重命名为 types.ts

很奇怪,它被直接导入 index.tsx 没有问题,但是 src 目录中的任何助手 files/functions 都会给我错误。

我的 NextJS 应用程序出现此错误,因为我在

中缺少 export
export function getStaticProps()

最小可重现示例

一个干净的最小示例将对 Webpack 初学者有所帮助,因为基于使用情况的自动拆分是如此神奇。

工作你好世界基线:

pages/index.js

// Client + server code.

export default function IndexPage(props) {
  return <div>{props.msg}</div>
}

// Server-only code.

export function getStaticProps() {
  return { props: { msg: 'hello world' } }
}

package.json

{
  "name": "test",
  "version": "1.0.0",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "12.0.7",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  }
}

运行 与:

npm install
npm run dev

现在让我们添加一个虚拟 require('fs') 来炸毁东西:

// Client + server code.

export default function IndexPage(props) {
  return <div>{props.msg}</div>
}

// Server-only code.

const fs = require('fs')

export function getStaticProps() {
  return { props: { msg: 'hello world' } }
}

失败:

Module not found: Can't resolve 'fs' 

这并不奇怪,因为 Next.js 无法知道 fs 只是服务器,我们不希望它只是忽略随机 require 错误,对吧? Next.js 只知道 getStaticProps 因为那是硬编码的 Next.js 函数名。

好的,让我们通过在 getStaticProps 中使用 fs 来通知 Next.js,以下再次起作用:

// Client + server code.

export default function IndexPage(props) {
  return <div>{props.msg}</div>
}

// Server-only code.

const fs = require('fs')

export function getStaticProps() {
  fs
  return { props: { msg: 'hello world' } }
}

心碎了。所以我们知道,在 getStaticProps 的正文中提到 fs,即使是像上面这样无用的,也会让 Next.js/Webpack 明白它将是仅限服务器的。

getServerSidePropsgetStaticPaths 的情况相同。

高阶组件 (HOC) 必须在它们自己的文件中

现在,我们在不同但相似的页面中分解 IndexPagegetStaticProps 的方法是使用 HOC,它们只是 return 其他函数的函数。

HOC 通常会放在 pages/ 之外,然后从多个位置需要,但是当您要将事情分解出来进行概括时,您可能会想将它们直接放在 pages/ 临时文件,例如:

// Client + server code.

import Link from 'next/link'

export function makeIndexPage(isIndex) {
  return (props) => {
    return <>
      <Link href={isIndex ? '/index' : '/notindex'}>
        <a>{isIndex ? 'index' : 'notindex'}</a>
      </Link>
      <div>{props.fs}</div>
      <div>{props.isBlue}</div>
    </>
  }
}

export default makeIndexPage(true)

// Server-only code.

const fs = require('fs')

export function makeGetStaticProps(isBlue) {
  return () => {
    return { props: {
      fs: Object.keys(fs).join(' '),
      isBlue,
    } }
  }
}

export const getStaticProps = makeGetStaticProps(true)

但如果你这样做,你会很难过地看到:

Module not found: Can't resolve 'fs' 

所以我们明白了另一件事:fs 用法必须直接在 getStaticProps 函数体内,Webpack 无法在子函数中捕获它。

解决这个问题的唯一方法是为仅用于后端的内容创建一个单独的文件,如:

pages/index.js

// Client + server code.

import { makeIndexPage } from "../front"

export default makeIndexPage(true)

// Server-only code.

import { makeGetStaticProps } from "../back"

export const getStaticProps = makeGetStaticProps(true)

pages/notindex.js

// Client + server code.

import { makeIndexPage } from "../front"

export default makeIndexPage(false)

// Server-only code.

import { makeGetStaticProps } from "../back"

export const getStaticProps = makeGetStaticProps(false)

front.js

// Client + server code.

import Link from 'next/link'

export function makeIndexPage(isIndex) {
  return (props) => {
    console.error('page');
    return <>
      <Link href={isIndex ? '/notindex' : '/'}>
        <a>{isIndex ? 'notindex' : 'index'}</a>
      </Link>
      <div>{props.fs}</div>
      <div>{props.isBlue}</div>
    </>
  }
}

back.js

// Server-only code.

const fs = require('fs')

export function makeGetStaticProps(isBlue) {
  return () => {
    return { props: {
      fs: Object.keys(fs).join(' '),
      isBlue,
    } }
  }
}

Webpack 必须看到名称 makeGetStaticProps 被分配给 getStaticProps,因此它决定整个 back 文件仅供服务器使用。

请注意,如果您尝试将 back.jsfront.js 合并到一个文件中,它不起作用,可能是因为当您这样做时 export default makeIndexPage(true) webpack 必然会尝试拉取整个 front.js 文件进入前端,其中包括 fs,所以它失败了。

这导致库文件在以下之间自然(基本上几乎是强制性的)拆分:

  • front.jsfront/*:前端+后端文件。这些对于前端是安全的。后端可以做前端可以做的任何事情(我们正在做 SSR 对吗?)所以这些也可以从后端使用。

    也许这就是许多官方示例中常规的“components”文件夹背后的想法。但这是一个糟糕的名字,因为该文件夹不仅应该包含组件,还应该包含将从前端使用的库组件。

  • back.jsback/*(或者 front/* 之外的任何内容):仅限后端文件。这些只能由后端使用,在前端导入它们会导致错误

如果尝试在 Next.js 中使用 fs-extra,这对我有用

module.exports = {
  webpack: (config) => {
    config.resolve.fallback = { fs: false, path: false, stream: false, constants: false };
    return config;

  }
}

我在这上面花了几个小时,解决方案也在 Whosebug 上,但在不同的问题上 ->

特此请求 MOD 转发此问题的许可,因为此问题是第一个出现在 Google 上的问题,可能越来越多的人会遇到与我相同的问题, 所以我会尽量为他们省点力气

Soo,您需要将此添加到您的 next.config.js

    module.exports = {
  future: {
    webpack5: true, // by default, if you customize webpack config, they switch back to version 4. 
      // Looks like backward compatibility approach.
  },
  webpack(config) {
    config.resolve.fallback = {
      ...config.resolve.fallback, // if you miss it, all the other options in fallback, specified
        // by next.js will be dropped. Doesn't make much sense, but how it is
      fs: false, // the solution
    };

    return config;
  },
};

它对我来说就像一个魅力

我 运行 在 NextJS 应用程序中使用它,因为我在 getServerSideProps() 正下方定义了一个新的辅助函数,但尚未在 getServerSideProps() 中调用该函数。

我不确定为什么这会造成问题,但确实会造成问题。我只能通过调用该函数、删除它或将其注释掉来让它工作。