78

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
  • 7,153
  • 3
  • 19
  • 27
user3799968
  • 967
  • 2
  • 7
  • 12

9 Answers9

65

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
  • 933
  • 8
  • 11
  • 2
    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
37

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
  • 29,321
  • 31
  • 106
  • 146
  • 6
    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
  • 4
    @SuuSoJeat that is because the version of your webpack is newer from this answer, [see my answer](https://stackoverflow.com/a/64428818/6791254) instead – kia nasirzadeh Oct 19 '20 at 13:52
  • 3
    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
20

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,664
  • 1
  • 9
  • 8
18

Add below configuration to your webpack.config.js

resolve: {
  fallback: {
    fs: false
  }
}
kia nasirzadeh
  • 2,518
  • 20
  • 26
  • 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
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
  • 11,739
  • 4
  • 37
  • 44
7

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
  • 4,570
  • 2
  • 21
  • 38
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
  • 721
  • 10
  • 17
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
  • 53
  • 5
1

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

npm install --save --force webpack@webpack-3
zx485
  • 26,827
  • 28
  • 51
  • 55