我正在使用流行的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
。
没有任何问题
您可以在getStaticProps
或getServerSideProps
安全地使用fs
getServerSideProps
,无需额外配置。 确保您在数据生命周期中引用了变量,以便正确地将其删除。
您可以使用此工具直观地了解其工作原理!
如果您仍在使用getInitialProps
构建旧版 Next.js 版本,请阅读以下内容👇
提供的代码无效——该文件在渲染期间永远不会在客户端可用:
请记住,您只能在_服务器上_时进行与 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
没有被淘汰。
一个例子:
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`)
import { BLOG_PATH, blogFilePaths } from './mdxUtils'
export const getStaticProps = () => {
const posts = blogFilePaths.map((filePath) => {
...
}
return { props: { posts } }
}
如您所见,我没有在index.js
任何地方使用BLOG_PATH
,但仍在导入它。 我只使用blogFilePaths
所以它给了我这个错误。
谢谢@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
我建议您阅读文档以找到解决方案:)
太棒了,我错过了文档中的那部分,谢谢! 我会更新我的代码👍🏽
最有用的评论
更新现代 Next.js (9.4+)
您可以在
getStaticProps
或getServerSideProps
安全地使用fs
getServerSideProps
,无需额外配置。 确保您在数据生命周期中引用了变量,以便正确地将其删除。您可以使用此工具直观地了解其工作原理!
如果您仍在使用
getInitialProps
构建旧版 Next.js 版本,请阅读以下内容👇提供的代码无效——该文件在渲染期间永远不会在客户端可用:
https://github.com/TidyIQ/nextjs-issue/blob/aef67b12d91d299d0978550005a40cbb34f74b71/pages/index.js#L5
请记住,您只能在_服务器上_时进行与 FS 相关的操作。 这意味着您不能在渲染时使用
fs
。如果您使用
fs
,请确保它仅在getInitialProps
。您可能还需要创建一个包含以下内容的
next.config.js
文件来构建客户端包: