92

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?

qzb
  • 8,163
  • 3
  • 21
  • 27
user3799968
  • 1,117
  • 2
  • 8
  • 14

10 Answers10

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.

Joe Withey
  • 983
  • 8
  • 11
  • 4
    Even though webpack is much newer, the `target: 'node'` line is still important and what makes this work on webpack v4 – yagni Oct 06 '21 at 16:40
45

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
}
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162
  • 7
    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 Oct 12 '20 at 13:52
  • 5
    @SuuSoJeat that is because the version of your webpack is newer from this answer, [see my answer](https://stackoverflow.com/a/64428818/6791254) instead – TechDogLover OR kiaNasirzadeh Oct 19 '20 at 13:52
  • 6
    Adding node: { fs: "empty" } to webpack.config.js did not work but adding "browser": { "fs": false } to package.json did! Success! – ariebear Dec 02 '20 at 07:04
  • package.json entry did the job. Thanks :) – Mayank Dudakiya Sep 07 '21 at 12:19
  • 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! – Hamed Mahdizadeh Nov 15 '21 at 15:35
22

Add below configuration to your webpack.config.js

resolve: {
  fallback: {
    fs: false
  }
}
  • this worked for me when updating to laravel-mix v6 – Stetzon Apr 15 '21 at 12:25
  • 1
    @kia nasirzadeh I have a similar error with Laravel 8 that I can't solve. Could you please help me? https://stackoverflow.com/questions/68032168/how-can-i-solve-the-problem-with-module-os-and-fs-using-npm-in-laravel-8 – marco987 Jun 18 '21 at 10:49
21

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.

PDG
  • 1,774
  • 1
  • 10
  • 8
9

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")')
wizulus
  • 5,653
  • 2
  • 23
  • 40
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.

Gomino
  • 12,127
  • 4
  • 40
  • 49
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,
...
OpSocket
  • 997
  • 11
  • 19
2

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

More info on: official documentation

TonyStark
  • 51
  • 5
0

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.

Weilory
  • 2,621
  • 19
  • 35
-2

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

npm install --save --force webpack@webpack-3
zx485
  • 28,498
  • 28
  • 50
  • 59