Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack Uncaught ReferenceError: require is not defined after removing node_modules from bundle.js

bundle.js      2.83 kB   0  [emitted]  main
bundle.js.map  3.36 kB   0  [emitted]  main

When I add the code below with the custom externals, I can remove the node_modules from being directly included in the bundle.js output.

bundle.js      743 kB       0  [emitted]  main
bundle.js.map  864 kB       0  [emitted]  main

This significantly reduces the bundle size. But I get an error in the browser saying: Uncaught ReferenceError: require is not defined in the browser. Does anyone know how to fix this issue?

var path = require("path"),
  fs = require("fs");

// return what's in the node modules folder apart from ".bin"
const nodeModules = fs
  .readdirSync("./node_modules")
  .filter(d => d != ".bin");

/**
 * Remove non-direct references to modules from bundles
 *
 * @param {any} context
 * @param {any} request
 * @param {any} callback
 * @returns
 */
function ignoreNodeModules(context, request, callback) {
  // IF someone is importing a module e.g. "import {chatModule} from
  // "./components/chat" using a relative path, then we're okay with them bringing
  // in into the bundle
  if (request[0] == ".") 
    return callback();

  // IF someone is doing "import {Subject} from "rxjs/Subject" only want to know
  // if first part is a node_module
  const module = request.split("/")[0];
  if (nodeModules.indexOf(module) !== -1) {
    // append "commonjs " - tells webpack to go and grab from node_modules instead
    // of including in bundle
    return callback(null, "commonjs " + request);
  }

  return callback();
}

module.exports = {
  entry: "./src/index.tsx",
  output: {
    filename: "bundle.js"
  },
  devtool: "source-map",
  resolve: {
    extensions: ["", ".ts", ".tsx", ".js"]
  },
  module: {
    loaders: [
      {
        test: /\.ts(x?)$/,
        loader: "ts-loader"
      }
    ]
  },
  // Runs our custom function everytime webpack sees a module
  externals: [ignoreNodeModules]
}
like image 583
Clement Avatar asked Dec 04 '16 12:12

Clement


1 Answers

Your bundle is smaller because you're not including your node_modules, but this leads to a fundamental problem: you no longer send your dependencies to the browser, so your code can't run at all. As you probably know, browsers don't natively support require(), so your current ignoreNodeModules function tells Webpack to skip bundling them and leave in the require(), but the browser doesn't know how to handle it.

If you want to reduce bundle size, consider using Webpack's code splitting so that you only bundle dependencies that are needed for each page/section. Alternatively, you could consider using a browser-side require() loader such as RequireJS.

Using externals is only really useful for distributing server-side Node libraries, where you would expect consumers of your library to provide your dependencies rather than bundling them with your library.

The comments on the documentation about externals are also worth reading for some further context on the issue.

like image 169
Aurora0001 Avatar answered Oct 24 '22 07:10

Aurora0001