Next.js: 找不到模块:无法解析“fs”

创建于 2019-07-05  ·  13评论  ·  资料来源: vercel/next.js

错误报告

描述错误

我正在使用流行的find-up npm 包,它具有locate-path作为依赖项。 locate-path fs在其代码中需要

当我尝试运行我的应用程序时,我收到以下错误消息:

[ error ] ./node_modules/locate-path/index.js
Module not found: Can't resolve 'fs' in 'C:\...\node_modules\locate-path'
Could not find files for /index in .next/build-manifest.json
Promise { <pending> }
ModuleNotFoundError: Module not found: Error: Can't resolve 'fs' in 'C:\...\node_modules\locate-path'
    at factory.create (C:\...\node_modules\webpack\lib\Compilation.js:823:10)
    at factory (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:397:22)
    at resolver (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:130:21)
    at asyncLib.parallel (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:224:22)
    at C:\...\node_modules\neo-async\async.js:2830:7
    at C:\...\node_modules\neo-async\async.js:6877:13
    at normalResolver.resolve (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:214:25)
    at doResolve (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:184:12)
    at hook.callAsync (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn0 (eval at create (C:\...\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
    at resolver.doResolve (C:\...\node_modules\enhanced-resolve\lib\UnsafeCachePlugin.js:37:5)
    at hook.callAsync (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn0 (eval at create (C:\...\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
    at hook.callAsync (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
    at _fn0 (eval at create (C:\...\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:27:1)
    at resolver.doResolve (C:\...\node_modules\enhanced-resolve\lib\DescriptionFilePlugin.js:42:38)

在 locate-path 存储库中创建了一个

再现

克隆https://github.com/TidyIQ/nextjs-issue并运行npm run dev

预期行为

没有任何问题

系统信息

  • 操作系统:Windows 10
  • Next.js 版本:8.1.1-canary.67

最有用的评论

更新现代 Next.js (9.4+)

您可以在getStaticPropsgetServerSideProps安全地使用fs getServerSideProps无需额外配置。 确保您在数据生命周期中引用了变量,以便正确地将其删除。

您可以使用此工具直观地了解其工作原理!

如果您仍在使用getInitialProps构建旧版 Next.js 版本,请阅读以下内容👇


提供的代码无效——该文件在渲染期间永远不会在客户端可用:

https://github.com/TidyIQ/nextjs-issue/blob/aef67b12d91d299d0978550005a40cbb34f74b71/pages/index.js#L5

请记住,您只能在_服务器上_时进行与 FS 相关的操作。 这意味着您不能在渲染时使用fs

如果您使用fs ,请确保它仅在getInitialProps

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

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

    return config
  }
}

所有13条评论

更新现代 Next.js (9.4+)

您可以在getStaticPropsgetServerSideProps安全地使用fs getServerSideProps无需额外配置。 确保您在数据生命周期中引用了变量,以便正确地将其删除。

您可以使用此工具直观地了解其工作原理!

如果您仍在使用getInitialProps构建旧版 Next.js 版本,请阅读以下内容👇


提供的代码无效——该文件在渲染期间永远不会在客户端可用:

https://github.com/TidyIQ/nextjs-issue/blob/aef67b12d91d299d0978550005a40cbb34f74b71/pages/index.js#L5

请记住,您只能在_服务器上_时进行与 FS 相关的操作。 这意味着您不能在渲染时使用fs

如果您使用fs ,请确保它仅在getInitialProps

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

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

    return config
  }
}

我在本地安装时遇到了同样的问题,实际上是 vanilla 安装,但是在 nextjs 的示例中,这似乎不是问题
https://github.com/zeit/next.js/tree/5787cbd9de33ea9add7cadeb04689b0d4b02976d/examples/blog-starter

是什么让它在不修改配置文件的情况下工作?

仅在 getStaticProps / getServerSideProps 中使用fs ,因为它们已从浏览器包中删除。

我发现了问题所在。 如果我导入一个使用fs的函数,但不在 getStaticProps 中运行/使用该函数,它将最终包含在浏览器包中。 一旦该函数在 getStaticProps 中被引用,它将停止出现在浏览器包中。

我猜有一些隐藏的逻辑可以删除在 getStaticProps 中使用但在主导出中未使用的导入。 我花了几个小时调试直到我可以重现,也许值得在文档的某个地方做一个旁注:)

隐藏的逻辑不就是webpack的摇树吗? 想起来就说得通了,Next 并没有在浏览器包中导入getStaticProps ,因此它删除了其中使用的导入函数。

如果你没有在任何地方引用它,我猜 webpack 认为你导入它是为了副作用,所以它仍然包含在每个包中。

隐藏的逻辑不就是webpack的摇树吗? 想起来就说得通了,Next 并没有在浏览器包中导入getStaticProps ,因此它删除了其中使用的导入函数。

如果你没有在任何地方引用它,我猜 webpack 认为你导入它是为了副作用,所以它仍然包含在每个包中。

不,webpack 树摇动不够复杂,无法以这种方式摇动这些导出。 摇树 getStaticProps / getServerSideProps / getStaticPaths 由我们创建的这个自定义 Babel 插件处理: https :

哦,谢谢指点,看来我高估了 webpack :)

_within_ getServerSideProps会发生这种情况的任何原因?

大家好。 像@aloukissas一样,我在index.js getStaticProps()使用dotenv时也有同样的问题。 添加next.config.js文件时,它得到解决,如@Timer初始注释所示。

任何线索为什么会发生这种情况? 我正在唱Next.js v.9.4.0

谢谢!

我在使用fast-glob遇到了这个错误。

我使用这个很棒的工具来了解捆绑在客户端的代码。

结果,我从使用fast-glob的文件中导入了一个变量,该文件在内部使用了fs但我没有在getStaticProps内的任何地方使用该变量,因此文件导入了fast-glob没有被淘汰。

一个例子:

mdxUtils.js

import glob from 'fast-glob'
import path from 'path'

export const BLOG_PATH = path.join(process.cwd(), 'posts')
export const blogFilePaths = glob.sync(`${BLOG_PATH}/blog/**/*.mdx`)

索引.js

import { BLOG_PATH, blogFilePaths } from './mdxUtils'

export const getStaticProps = () => {
  const posts = blogFilePaths.map((filePath) => {
    ...
  }
  return { props: { posts } }
}

如您所见,我没有在index.js任何地方使用BLOG_PATH ,但仍在导入它。 我只使用blogFilePaths所以它给了我这个错误。

更多上下文 → https://github.com/vercel/next.js/discussions/17138

谢谢@deadcoder0904这是我的代码:

import Layout from '../components/template'
import Main from '../components/main'
import Menu from '../components/menu'
import 'dotenv/config'

export async function getStaticProps () {
  const avatarLocation = process.env.AVATAR_URL
  const avatarTitle = process.env.AVATAR_TITLE

  return {
    props: {
      avatarLocation,
      avatarTitle
    }
  }
}

export default function RenderMainPage ({ avatarLocation, avatarTitle }) {
  return (
    <Layout
      avatarURL={avatarLocation}
      topLeft={<Menu />}
      middle={<Main avatarURL={avatarLocation} avatarTitle={avatarTitle} />}
    />
  )
}

您提到的工具显示import 'dotenv/config'包含在客户端代码中,这可能导致错误出现。 问题是我需要它来读取 env 变量。

可能还有另一种更好的方法可以做到,我还在学习 Next.js :)

@ig-perez 从 Next v9.4 开始,他们有一种内置的方式来加载环境变量 → https://nextjs.org/docs/basic-features/environment-variables

我建议您阅读文档以找到解决方案:)

太棒了,我错过了文档中的那部分,谢谢! 我会更新我的代码👍🏽

此页面是否有帮助?
0 / 5 - 0 等级