97

I'm using node.js and webpack to create a bundle. From what I've read, node.js should contain fs module for managing files. However when I call require("fs") I get an Cannot find module "fs" error. What should I do?

0

11 Answers 11

70

I came across this problem myself when bundling with webpack and found the answer on this thread.

The way to solve it for me was to use the following config:

module.exports = {
  entry: "./app",
  output: {
    path: __dirname,
    filename: "bundle.js"
  },
  module: {
      loaders: [
          {  
              test: /\.js$/,
              exclude: 'node_modules',
              loader: 'babel',
              query: {presets: ['es2015']},
          }
      ]
  },
  target: 'node'
};

By setting target to node webpack will make the necessary changes to bundle your node application

Edit: This answer targeted webpack 1.x which has now been superseded.

Sign up to request clarification or add additional context in comments.

3 Comments

Even though webpack is much newer, the target: 'node' line is still important and what makes this work on webpack v4
yeah agree, just having target: 'node' works, moreover, with webpack v5.88.2 the loaders strucutre has changed refer: webpack.js.org/concepts/loaders.
Just check the NODE version, maybe some package requires a newer one
47

If you are running your webpack bundle in nodejs environment then target: 'node' is required in webpack.config.js file otherwise webpack takes default value as web for target check here.

You can resolve the issue in two ways

Add below configuration to your webpack.config.js

node: {
    fs: "empty"
}

OR

Add below configuration to your package.json

"browser": {
    "fs": false
}

Edit:

promising fix is

"browser": {
   "fs": false
}

4 Comments

I got this error after I added the fs. Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema. - configuration.node has an unknown property 'fs'. These properties are valid: object { __dirname?, __filename?, global? } -> Options object for node compatibility features.
@SuuSoJeat that is because the version of your webpack is newer from this answer, see my answer instead
Adding node: { fs: "empty" } to webpack.config.js did not work but adding "browser": { "fs": false } to package.json did! Success!
I had problem with 'path' in some legacy code and I did the exact opposite thing. After removing the "browser": { "path": false} now the webpack injects the correct object!
26

Add below configuration to your webpack.config.js

resolve: {
  fallback: {
    fs: false
  }
}

2 Comments

this worked for me when updating to laravel-mix v6
@kia nasirzadeh I have a similar error with Laravel 8 that I can't solve. Could you please help me? stackoverflow.com/questions/68032168/…
22

I had the same issue when bundling a NWjs application using webworkers (which in turn had node enabled).

The solution I found was to include each native module I used in externals with the prefix commonjs to the name of the module. For example:

    ...
    target: "webworker", // or 'node' or 'node-webkit'
    externals:{
        fs:    "commonjs fs",
        path:  "commonjs path"
    }
    ...

I've done the same for targets "webworker" and "node-webkit" in different projects to solve the same issue.

Comments

10

I needed to build a class that would use fetch if executed in a browser, or fs if executed in node. For other reasons, it was impractical to produce separate bundles, so I produced a single browser-targeted bundle.

The solution I used was to use eval('require("fs")') if the script was running in node.

const fs = eval('require("fs")')

Browser-safe (fs is null in the browser):

const fs = typeof window === 'object'
    ? null
    : eval('require("fs")')

Comments

8

After trying everything I found on the internet (target, externals, node configs), the only solution that actually worked for me was replacing:

const filesystem = require("fs")
        or
import fs from "fs"

by the special webpack version

const fs = __non_webpack_require__("fs")

This generates a require function that is not parsed by webpack.

1 Comment

My Electron doesn't understand what __non_webpack_require__ is..
3

In addition to the answer of PDG

I'm used to this short copy/paste candy.

Using path and fs :

var nodeModules = {};
fs.readdirSync(path.resolve(__dirname, 'node_modules'))
  .filter(x => ['.bin'].indexOf(x) === -1)
  .forEach(mod => { nodeModules[mod] = `commonjs ${mod}`; });

// Before your webpack configuration

module.exports = {
...
}

Then inside your configuration file, include the nodeModules variable in the externals

...
externals: nodeModules,
...

Comments

2

It would be more elegant to use pre-defined solution as:
Adding target: 'node' to webpack config file.

More info on: official documentation

Comments

1

To be clear, I am not a pro node.js developer, just an unfortunate guy who is on frontend try to use somebody else's code.

you may have wondered why error occurs, obviously, node.js provides more than frontend, many opensource thereby integrite modules such as fs, path, for building backend approaches.

So how the heck can I ignore, you know the backend part of implementation, in order to get this work?


Option 1

nullify backend modules

add to webpack.config.js

resolve: {
    fallback: {
        fs: false,
        path: false,
    },
},

also add corresponding to package.json, otherwise you are likely to get a Filed 'browser' doesn't contain a valid alias configuration

"browser": {
    "fs": false,
    "path": false,
}, 

this will do if the dependency does not rely on the backend module, that means, not doing stuff like writing local file during runtime, and not accessing the prototype from any declared in that module.


Option 2

browserify polyfill

polyfill are basically a piece of code that fill the functionality gap, browserify provides object that stimulate that dependency's interface, with that help, in minified code, for example, if fs.readFile is called, it won't throw a undefined error, but the function would return null and continue to run.

resolve: {
    fallback: {
        fs: require.resolve("browserify-fs"),,
        path: require.resolve("path-browserify"),,
    },
},

you may notice the prefix browserify- and surfix -browserify are different, it's not a typo, depending on the module you actually need to search for a valid name on npm. here are some common names you can dirrectly use:

  • browserify-fs
  • browserify-zlib
  • browserify-shim
  • path-browserify
  • stream-browserify
  • crypto-browserify

here's a quick note, after plugin multiple polyfill, the production mode build may compile a file with enomous file size. you may wanna directly use development mode, though it writes tons of file.

Comments

0

I had a similar issue while using webpack to bundle a typescript project for a Cloud Run Function in GCP. The problem with the fs module breaking the build is common. I tried all the suggested solutions, but none worked for me.

If you're still having this problem, try this:

In your webpack.config file, add this line:

externals: [nodeExternals()] 

This will exclude external node modules packages from the final bundled file.

When deploying, only upload your build file (e.g., index.js) along with the package.json. But before uploading, delete all the scripts in the package.json file.

i.e. the package.json should look something like this:-

{
  "name": "abc",
  "version": "1.0.0",
  "description": "abc",
  "main": "index.js",  //this is important make sure this filename is the your bindles file name
  "scripts": { delete everything inside here }, // add this in case some other failure - "clean": "npm clean cache"
  "dependencies": {...}
  "devDependencies": {...}
 }

By default, GCP Cloud Run installs everything from the package.json file. If there are scripts, it will run them too, which can cause issues. That’s why you should remove them before uploading.

Hope this helps!

Comments

-2

For the solution we are building we had to force an older version of webpack:

npm install --save --force webpack@webpack-3

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.