Skip to main content

How to Resolve the "Module not found: Can't resolve" Error in Webpack in JavaScript

The error Module not found: Error: Can't resolve '...' (e.g., 'fs', 'tls', 'net', 'path') is a common issue in modern frontend development, especially in projects using Webpack 5+. This error occurs when a piece of your client-side JavaScript code tries to import a module that is built-in to the Node.js environment, not the browser.

This guide will explain the fundamental reason this error happens and show you the correct, modern way to solve it by configuring your Webpack fallback settings.

The Core Problem: Node.js Modules Don't Exist in the Browser

Modules like fs (file system), tls (transport layer security), net (networking), path, crypto, and http are core Node.js APIs. They provide access to the computer's file system, network stack, and other operating system features. For security reasons, browsers are sandboxed and do not have access to these modules.

The Can't resolve '...' error is Webpack telling you: "You're trying to bundle a library that depends on a Node.js-specific module, but I can't find a browser-compatible version of it."

This became a very common error with the release of Webpack 5, which removed the automatic polyfills for these modules that were included in previous versions. A "polyfill" is a piece of code that provides a browser-friendly substitute for a native Node.js module.

The Solution: Configuring Webpack's resolve.fallback

The correct way to handle this is to explicitly tell Webpack what to do when it encounters an import for a Node.js core module. You do this in the resolve.fallback section of your Webpack configuration.

You have two main choices for each module:

  1. Provide a browser-compatible polyfill: If your code actually needs the functionality of the module, you can install a polyfill library from npm.
  2. Provide an empty module (false): If your code doesn't actually need the module (e.g., it's an optional dependency of a library that you're not using), you can tell Webpack to substitute it with an empty module. This is the most common solution.

How to Apply the Solution

The implementation depends on your project's setup.

In a Custom webpack.config.js

If you have direct access to your webpack.config.js file, add or modify the resolve.fallback property.

For example, your build is failing with errors like Can't resolve 'fs', Can't resolve 'tls', and Can't resolve 'net'.

Solution:

// webpack.config.js
module.exports = {
// ... other configurations
resolve: {
fallback: {
"fs": false,
"tls": false,
"net": false,
"path": require.resolve("path-browserify") // Example of using a polyfill
}
},
// ... other configurations
};
note

In this example, we've told Webpack to substitute fs, tls, and net with empty modules, but we've provided a polyfill for the path module.

In a Create React App Project (without ejecting)

Create React App hides the Webpack configuration. To modify it without running the irreversible eject command, you can use a tool like react-app-rewired and customize-cra.

  1. Install the packages:

    npm install react-app-rewired customize-cra --save-dev
  2. Update package.json scripts:

    "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test"
    }
  3. Create config-overrides.js: In the root of your project, create a config-overrides.js file.

    config-overrides.js:

    const { override } = require('customize-cra');

    module.exports = override(
    (config) => {
    config.resolve.fallback = {
    ...config.resolve.fallback,
    "fs": false,
    "tls": false,
    "net": false,
    };
    return config;
    }
    );

In a Next.js Project

For a Next.js project, you can modify the Webpack configuration directly in your next.config.js file.

next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
webpack: (config) => {
config.resolve.fallback = {
...config.resolve.fallback,
fs: false,
tls: false,
net: false,
};
return config;
},
};

module.exports = nextConfig;

Installing Polyfills (When Necessary)

If you find that your application does need the functionality of a Node.js module (a common example is crypto or stream), you must install a browser-compatible polyfill.

For example, you get the error Module not found: Error: Can't resolve 'stream'.

Solution:

  1. Install the polyfill:
    npm install stream-browserify
  2. Configure the fallback in Webpack:
    // webpack.config.js (or equivalent override file)
    resolve: {
    fallback: {
    "stream": require.resolve("stream-browserify")
    }
    }

Conclusion

The "Can't resolve" error for Node.js core modules is a direct consequence of Webpack 5 no longer providing automatic polyfills.

  • The root cause is always a library intended for the Node.js environment being included in your client-side browser bundle.
  • The correct solution is to configure the resolve.fallback property in your Webpack configuration.
  • For modules your code doesn't actually use, set the fallback to false to replace them with an empty module. This is the most common fix.
  • For modules whose functionality you do need, install a browser-compatible polyfill from npm and point to it in the fallback configuration.