Skip to content

How to Resolve the "Module not found: Can't resolve" Error for Node.js Core Modules in JavaScript

Fix the Webpack 5+ 'Can't resolve' error for Node.js modules like assert, util, or crypto by ignoring them in package.json or webpack.config.js or installing browser-compatible polyfills.

When working with modern JavaScript bundlers like Webpack 5+, you may encounter the Module not found: Error: Can't resolve '...' error for modules like assert, util, crypto, http, stream, or other Node.js core modules.

This error occurs because Webpack 5 and newer versions no longer automatically include polyfills for native Node.js modules. This is a deliberate change to encourage front-end code to be independent of Node.js-specific APIs, which do not exist in the browser.

This guide will explain the two main solutions to this problem: either providing a browser-compatible polyfill for the module or, more commonly, telling Webpack to ignore it.

The Core Problem: Webpack 5+ No Longer Polyfills Node.js Modules

In the past, bundlers like Webpack would often automatically bundle a browser-friendly version (a "polyfill") of a Node.js module if it was referenced in your code. This was convenient but could lead to large, unnecessary libraries being included in your front-end bundle.

Webpack 5 stopped this behavior. Now, if a package you are using was originally written for Node.js and contains a line like const assert = require('assert');, Webpack will fail with an error because it doesn't know how to resolve assert in a browser environment.

Example of the error:

Module not found: Error: Can't resolve 'assert' in ...

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.

This error message is very informative. It tells you exactly what has changed and gives you two options: polyfill it or exclude it.

Solution 1 (Most Common): Telling Webpack to Ignore the Module

In over 99% of cases, you do not actually need the Node.js module in your client-side code. It's often included as an optional dependency or for a server-side-only feature of a library. The easiest and most common solution is to tell Webpack that it can ignore this module or substitute it with an empty one.

For create-react-app (and similar tools)

Many build toolchains look for a browser field in your package.json file to handle browser-specific configurations.

The solution is to add a browser field to your package.json and set the module to false.

// package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "dependencies": { ... },

  // Add this section
  "browser": {
    "assert": false,
    "util": false,
    "stream": false,
    "crypto": false,
    "http": false,
    "https": false,
    "os": false,
    "url": false
  }
}

For Custom Webpack Configurations

If you have direct access to your webpack.config.js file, you can achieve the same result using the resolve.fallback property.

Solution:

// webpack.config.js
module.exports = {
  // ... other config
  resolve: {
    fallback: {
      "assert": false,
      "util": false,
      // ... add an entry for each module that fails
    }
  }
};

Solution 2 (Advanced): Installing and Using a Polyfill

In the rare case that your application actually needs the functionality of the Node.js module in the browser, you must provide a polyfill. A polyfill is a browser-compatible version of the native Node.js module.

Solution:

  1. Install the polyfill package. Many polyfills are available on npm. For example, for the stream module, you would use stream-browserify.
    npm install stream-browserify
  2. Configure Webpack to use it. In your webpack.config.js, update the resolve.fallback property to point the Node.js module name to the polyfill you installed.
    // webpack.config.js
    module.exports = {
      // ... other config
      resolve: {
        fallback: {
          "stream": require.resolve("stream-browserify")
        }
      }
    };

This is a more complex solution and should only be used if you are sure you need the module's functionality on the client side.

A Special Case: Next.js

In a Next.js application, Node.js modules can only be used in server-side code (like getServerSideProps or getStaticProps). If you try to import one in a component that renders on the client, you will get the "Can't resolve" error.

  • If you need the module's functionality: Make sure your code is running only on the server.
  • If you do not need the module: You can configure Next.js to ignore it on the client side by modifying your next.config.js file.

Solution (next.config.js)

// next.config.js for Webpack 5+
module.exports = {
  webpack: (config) => {
    // This is the standard way to disable client-side polyfills in Next.js.
    config.resolve.fallback = {
      fs: false,
      assert: false,
      // ... add other modules here
    };

    return config;
  },
};

Conclusion

The Module not found: Can't resolve ... error for Node.js core modules is a direct result of Webpack 5+ no longer providing automatic browser polyfills.

  • The most common and recommended solution is to tell your bundler to ignore the module, as it's usually not needed for client-side code. This is typically done by adding a browser field to your package.json or by configuring resolve.fallback in your webpack.config.js.
  • If you genuinely need the module's functionality in the browser, you must install a suitable polyfill package and configure Webpack to use it.
  • In frameworks like Next.js, this error is a signal that you are trying to use server-side code in a client-side component.
Navigation