找不到module:无法在 Next.js 应用程序中解析“fs”
如果您使用fs,请确保它仅在getInitialProps或内serverSideProps。(任何东西都包括服务器端渲染)。
您可能还需要创建一个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;
  },
};
注意:对于其他module,例如path,您可以添加多个参数,例如
{
  fs: false,
  path: false
}
fs,path或其他节点本机module只能在服务器端代码中使用,如“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"
然后我尝试在浏览器上加载节点module。我从 node_modules 复制了节点module的“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. 但这不是一种有效的方式。
可能是您尝试实现的module不应该在浏览器中运行。即它只是服务器端。
我在 NextJS 应用程序中遇到此错误,因为我export在
export function getStaticProps()
最小的可重复示例
一个干净的最小示例将对 Webpack 初学者有益,因为基于使用情况的自动拆分是如此令人兴奋的魔法。
工作你好世界基线:
页面/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' } }
}
包.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只是服务器,而且我们不希望它只是忽略随机要求错误,对吗?Next.js 只知道getStaticProps因为这是一个硬编码的 Next.js 函数名称。
好的,让我们通过使用fsinside通知 Next.js getStaticProps,以下再次起作用:
// 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' } }
}
头脑等于吹。所以我们明白,任何提到fs的主体内部getStaticProps,即使是像上面那样无用的,都会让 Next.js/Webpack 明白它将是仅限服务器的。
事情对getServerSideProps和 也一样getStaticPaths。
高阶组件 (HOC) 必须在它们自己的文件中
现在,我们分解出的方式IndexPage,并getStaticProps在不同但类似的网页是用肝卵圆细胞,这是刚刚返回其他函数的函数。
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 无法在子函数中捕获它。
解决此问题的唯一方法是为仅后端内容创建一个单独的文件,如下所示:
页面/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)
页面/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)
前端.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>
    </>
  }
}
返回.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.js和合并front.js到单个文件中,则它不起作用,可能是因为当您执行export default makeIndexPage(true)webpack时,它必然会尝试将整个front.js文件拉入前端,其中包括 fs,因此它失败了。
这导致库文件在以下之间自然拆分:
front.js和front/*:前端+后端文件。这些对前端来说是安全的。后端可以做前端可以做的任何事情(我们正在做 SSR 对吗?)所以那些也可以从后端使用back.js和back/*:仅后端文件。这些只能由后端使用,在前端导入它们会导致错误

