Web3.js – Resolve ‘Stream’ Module Not Found Error in React Project

nodejsreactweb3js

When I include web3 in a project I am getting node compile errors like this…

ERROR in ./node_modules/cipher-base/index.js 3:16-43

Module not found: Error: Can't resolve 'stream' in '/Users/xxx/dev/blockchain/xxx-truffle-react/node_modules/cipher-base'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
    - install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "stream": false }

I get these errors for packages:

stream-browserify
crypto-browserify
stream-http
https-browserify
url/
os-browserify/browser

I have successfully added web3 using

npm install web3

I also tried installing each of the troublesome packages as well using…

npm install crypto-browserify stream-browserify assert stream-http https-browserify os-browserify

which told me they were up to date

The dependencies section of my package-lock.json also has references to them

      "dependencies": {
        "@openzeppelin/contracts": "^4.5.0",
        "@testing-library/jest-dom": "^5.16.2",
        "@testing-library/react": "^12.1.4",
        "@testing-library/user-event": "^13.5.0",
        "assert": "^2.0.0",
        "crypto-browserify": "^3.12.0",
        "https-browserify": "^1.0.0",
        "os-browserify": "^0.3.0",
        "react": "^17.0.2",
        "react-dom": "^17.0.2",
        "react-scripts": "5.0.0",
        "stream-browserify": "^3.0.0",
        "stream-http": "^3.2.0",
        "web-vitals": "^2.1.4",
        "web3": "^1.7.1"
      }

After a bit of research there was a suggestion that the version of react-scripts needed to be to 4.0.3, so I tried that and it made no difference.

Before I do any major surgery like adding a post-install and altering code in dependency packages to fix it I am hoping I am doing something stupid and there's an easy answer.

Best Answer

I believe changing react-scripts to 4.0.3 and rerunning yarn install or npm install would've fixed this issue.

There are several ways to get around it but I like this way, as you don't have to eject or downgrade.

I did a workaround using react-app-rewired.

  1. Add these to your devDependencies and run yarn/npm install.
"devDependencies": {
    "assert": "^2.0.0",
    "buffer": "^6.0.3",
    "crypto-browserify": "^3.12.0",
    "https-browserify": "^1.0.0",
    "os-browserify": "^0.3.0",
    "process": "^0.11.10",
    "react-app-rewired": "^2.2.1",
    "stream-browserify": "^3.0.0",
    "stream-http": "^3.2.0",
    "url": "^0.11.0"
  }
  1. Change your scripts in package.json to run with react-app-rewired:
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  1. Create a config.overrides.js in your root folder and copy and paste the following into it:
const webpack = require("webpack");

module.exports = function override(config) {
  const fallback = config.resolve.fallback || {};
  Object.assign(fallback, {
    crypto: require.resolve("crypto-browserify"),
    stream: require.resolve("stream-browserify"),
    assert: require.resolve("assert"),
    http: require.resolve("stream-http"),
    https: require.resolve("https-browserify"),
    os: require.resolve("os-browserify"),
    url: require.resolve("url"),
  });
  config.resolve.fallback = fallback;
  config.plugins = (config.plugins || []).concat([
    new webpack.ProvidePlugin({
      process: "process/browser",
      Buffer: ["buffer", "Buffer"],
    }),
  ]);
  return config;
};