Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module not found: Can't resolve 'fs' #7755

Closed
TidyIQ opened this issue Jul 5, 2019 · 32 comments
Closed

Module not found: Can't resolve 'fs' #7755

TidyIQ opened this issue Jul 5, 2019 · 32 comments

Comments

@TidyIQ
Copy link

TidyIQ commented Jul 5, 2019

Bug report

Describe the bug

I'm using the popular find-up npm package, which has locate-path as a dependency. locate-path requires fs within it's code.

When I attempt to run my app I get the following error message:

[ 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)

I created an issue in the locate-path repo and they have confirmed the issue is not with them, but likely with webpack. I don't use webpack in my app so the issue must be arising from Next.js's use of webpack.

To Reproduce

Clone https://github.com/TidyIQ/nextjs-issue and run npm run dev.

Expected behavior

No issue

System information

  • OS: Windows 10
  • Version of Next.js: 8.1.1-canary.67
@Timer
Copy link
Member

Timer commented Jul 5, 2019

Update for modern Next.js (9.4+)

You can safely use fs within getStaticProps or getServerSideProps, no extra configuration required. Be sure you're referencing the variable in your data lifecycle so it's correctly tree shaken away.

You can use this tool to learn visually how it works!

If you're still building on a legacy Next.js version with getInitialProps, read below 👇


The provided code is not valid -- this file would never be available on the client side during rendering:

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

Remember, you can only do FS-related operations while on the server. This means you cannot use fs while rendering.

If you use fs, be sure it's only within getInitialProps.

You may also need to create a next.config.js file with the following content to get the client bundle to build:

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

    return config
  }
}

@bystrovo
Copy link

bystrovo commented May 3, 2020

I have the same problem on my local, practically vanilla install, however in the examples from nextjs this doesn not seem to be a problem
https://github.com/zeit/next.js/tree/5787cbd9de33ea9add7cadeb04689b0d4b02976d/examples/blog-starter

what makes it work there without modifying the config file?

@timneutkens
Copy link
Member

Only use fs in getStaticProps / getServerSideProps as those are eliminated from the browser bundle.

@bystrovo
Copy link

bystrovo commented May 6, 2020

I found out what the problem was. If I import a function that uses fs, but do not run/use the function inside getStaticProps, it will end up being included in the browser bundle. Once the function gets referenced inside getStaticProps it will stop appearing in the browser bundle.

I guess there is some hidden logic that removes imports used in getStaticProps but unused in main export. I spent a few hours debugging until I could reproduce, maybe worth having a sidenote somewhere in the docs :)

@tgroutars
Copy link

Isn't the hidden logic just webpack's tree shaking? Makes sense when you think of it, Next doesn't import getStaticProps in the browser bundle, so it removes the imported function used in it.

If you don't reference it anywhere, I guess webpack considers you imported it for side effects, so it still includes it in every bundle.

@timneutkens
Copy link
Member

Isn't the hidden logic just webpack's tree shaking? Makes sense when you think of it, Next doesn't import getStaticProps in the browser bundle, so it removes the imported function used in it.

If you don't reference it anywhere, I guess webpack considers you imported it for side effects, so it still includes it in every bundle.

No, webpack tree shaking is not sophisticated enough to shake these exports in that way. Tree shaking getStaticProps / getServerSideProps / getStaticPaths is handled by this custom Babel plugin we created: https://github.com/vercel/next.js/blob/canary/packages/next/build/babel/plugins/next-ssg-transform.ts

@tgroutars
Copy link

Oh thanks for the pointer, looks like I overestimated webpack :)

abendy added a commit to abendy/nextjs-redux-starter that referenced this issue Jun 27, 2020
@aloukissas
Copy link

Any reason this would be happening from within getServerSideProps?

@ig-perez
Copy link

Hi all. Like @aloukissas I have the same issue when using dotenv within my index.js getStaticProps(). It gets solved when adding the next.config.js file as shown in @Timer initial comment.

Any clues why is this happening? I'm unsing Next.js v.9.4.0

Thanks!

@deadcoder0904
Copy link

I had this error while using fast-glob.

I used this great tool to understand the code that gets bundled in the client-side.

Turned out, I was importing a variable from a file that uses fast-glob which internally uses fs but I wasn't using the variable anywhere inside getStaticProps so the files imports fast-glob weren't getting eliminated.

An example:

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`)

index.js

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

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

As you can see I am not using BLOG_PATH anywhere in index.js but still importing it. I am only using blogFilePaths so it gave me this error.

For more context → #17138

@ig-perez
Copy link

Thanks @deadcoder0904 this is my code:

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} />}
    />
  )
}

The tool you mention shows import 'dotenv/config' is included in the client code, and probably that is making the error appear. The thing is that I need it to read from the env variables.

Probably there's another better way to do it, I'm still learning Next.js :)

@deadcoder0904
Copy link

@ig-perez As of Next v9.4, they have a built-in way to load environment variables → https://nextjs.org/docs/basic-features/environment-variables

I suggest you read the docs to find the solution :)

@ig-perez
Copy link

That is awesome, I missed that part in the docs, thanks! I'll update my code 👍🏽

@stubar
Copy link

stubar commented Dec 9, 2020

I have a generic log fn which is some scenarios on the server I want it to write to disk, this is what I'm using...

 if (
      typeof window === 'undefined' &&
      serverRuntimeConfig.saveErrorLogToDisk
    ) {
      require('fs')...

I seem to recall "typeof window === 'undefined'" is a magic string that causes segments to be omitted from the client bundle

@borislemke
Copy link

borislemke commented Mar 6, 2021

In my case, it was a separation of FE and BE code. I had used barrel export in some folders, e.g:

| src
  | lib
    index.ts
    fe-code.ts
    be-code.ts

importing FE code by from the index will give this warning:

import FECode from "src/lib"

need to explicitly import or separate the folders

Option 1, do not use barrel export:

import FeCode from "src/lib/fe-code.ts"

Option 2, separate FE and BE code:

| src
  | fe-lib
    index.ts
    fe-code.ts
  | be-lib
    index.ts
    be-code.ts

// somewhere
import FECode from "src/fe-lib"

@femesq
Copy link

femesq commented Apr 3, 2021

For those trying webpack 5 on next.js, the fix is different:

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback.fs = false;
    }
    return config;
  },
}

Reference: https://webpack.js.org/migrate/5/#clean-up-configuration

@AIEAJN
Copy link

AIEAJN commented Jul 29, 2021

For those trying webpack 5 on next.js, the fix is different:

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback.fs = false;
    }
    return config;
  },
}

Reference: https://webpack.js.org/migrate/5/#clean-up-configuration

I tried this method and it didn't work, I have a problem with the pg module for postgresql, when I use it in my code it returns an error for fs, native pg and others. when I use this method I always get the same errors, I use version 5 of webpack

@deadcoder0904
Copy link

@AIEAJN you're probably exporting the pg module or fs on the client-side. try pasting your relevant code in https://next-code-elimination.vercel.app/ to see what gets shipped to client.

@AIEAJN
Copy link

AIEAJN commented Aug 2, 2021

ahhh okk i see now, thanks

@asci
Copy link

asci commented Aug 26, 2021

I had same issue, this comment helped #7755 (comment) But it took a while to find the culprit. Would be nice to have more informative error message, since it looks like a common mistake.

@glantucan
Copy link

glantucan commented Sep 9, 2021

I had this same issue (using fs/promises) and applying any of the proposed solutions works:

Solution 1:
Avoid uncalled functions on the module using fs/promises that was used from getStaticProperties()

Solution2
Adding this to your next.config.js

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback.fs = false;
    }
    return config;
  },
}

But these are workarounds, right? I mean, it's difficult to maintain, as it's difficult to detect that having functions on those modules that are not being called anymore is the cause of your problem.

I understand that tree shaking is tricky but, are there any plans to permanently fix this?

@TimNZ
Copy link

TimNZ commented Sep 12, 2021

Setting next.config.js: target = 'experimental-serverless-trace'
solved my problems with static page generation (MDX) using 'fs' module, that was erroring on resolve, and serverless build

@tettoffensive
Copy link

For those trying webpack 5 on next.js, the fix is different:

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback.fs = false;
    }
    return config;
  },
}

Reference: https://webpack.js.org/migrate/5/#clean-up-configuration

How do I tell next.js to use webpack 5. I still get this message info - Using webpack 4. Reason: custom webpack configuration in next.config.js https://nextjs.org/docs/messages/webpack5 when I update this section to the above.

@tkulpa
Copy link

tkulpa commented Oct 7, 2021

For those trying webpack 5 on next.js, the fix is different:

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback.fs = false;
    }
    return config;
  },
}

Reference: https://webpack.js.org/migrate/5/#clean-up-configuration

How do I tell next.js to use webpack 5. I still get this message info - Using webpack 4. Reason: custom webpack configuration in next.config.js https://nextjs.org/docs/messages/webpack5 when I update this section to the above.

Try this:

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

@dankerk
Copy link

dankerk commented Nov 3, 2021

When I add the proposed solution for webpack 5 the error disappears, but subsequent errors arise:
Module not found: Can't resolve 'http2'
and when I install that the next one appears
Module not found: Can't resolve 'tls'
and when I install that the next one appears... etc.

Does anyone have any more/other suggestions? I'm running "next": "^11.1.2",

@tettoffensive
Copy link

@dankerk I had similar errors because I was using apollo-server-micro v2. I just installed them (there ended up being maybe 3 packages and it worked. However, if this is the package your using consider switching to apollo-server-express v3: #30082

@dankerk
Copy link

dankerk commented Nov 4, 2021

@tettoffensive Unfortunately for me the rabbit hole went deeper than 3 packages. I installed like 10 of them then gave up. The trace leads back to the flamelink module I'm using.
The code runs server side so it should have access to fs (as it runs in a node environment). It's as if webpack doesn't understand that it has access to fs there.

Edit:

My problem turned out to be a stupid mistake on my end:
I had this in my code:

HomePage.getInitialProps = async () => {
// some firebaseAdmin code here...

But getInitialProps runs on the client side so I had to replace it with:

export async function getStaticProps() {
// some firebaseAdmin code here...

@riverscode
Copy link

When I add the proposed solution for webpack 5 the error disappears, but subsequent errors arise: Module not found: Can't resolve 'http2' and when I install that the next one appears Module not found: Can't resolve 'tls' and when I install that the next one appears... etc.

Does anyone have any more/other suggestions? I'm running "next": "^11.1.2",

I have the same proble with "next": "12.0.4",

@riefer02
Copy link

riefer02 commented Dec 24, 2021

Why is there no mention of this in the Next.js getServerSideProps caveats section? I recently stumbled upon an issue using plaiceholder npm package in a module.

Inside getServerSideProps, plaiceholder was being referenced in a function from another module. It was generating the Module not found: Can't resolve 'fs' while using getServerSideProps() . It worked locally, but after pushing to production it would break and I received a vague 500 server error.

The webpack 5 solution above did in fact fix the issue. Very happy, after several sessions of research. Cheers!

@lucasconstantino
Copy link
Contributor

Keep in mind Next' code elimination only works under /pages. If you have, say, a generic getServerSideProps elsewhere, it might not work as expected.

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Feb 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests