webpack: [Webpack 5] (minimal repro included!) __webpack_modules__[moduleId] is undefined

Bug report

What is the current behavior?

__webpack_require__ goes bang attempting to import a library local to our project (i.e. a sibling package in the same lerna monorepo).

We did not experience this problem in webpack 4.25.1, but we do experience the problem in webpack 5.0.0-beta.23.

Depending on how modern your browser is, you will encounter one of the following error messages:

Uncaught TypeError: __webpack_modules__[moduleId] is undefined
    __webpack_require__ http://localhost:8080/main.js:455
Uncaught TypeError: Cannot read property 'call' of undefined
    at __webpack_require__ (main.js:455)

You’ll recognise the latter from existing issues such as https://github.com/webpack/webpack/issues/6094. I think what I’ve found is just one of many ways to encounter this problem. I tried a lot of existing suggestions, but to no avail. Fortunately we have a repro this time. 🙂

If the current behavior is a bug, please provide the steps to reproduce.

Minimal repro repository here:
https://github.com/Birch-san/webpack-repro

Repository layout (* indicates a file output by build/installation):

  webpack-repro
* ├── node_modules
  ├── README.md
  ├── package-lock.json
  ├── package.json
  └── packages
      ├── lib
*     │   ├── dist
*     │   │   └── main.js
      │   ├── package.json
      │   ├── src
      │   │   ├── index.js
      │   │   └── utils.js
      │   └── webpack.config.js
      └── web
          ├── dist
          │   ├── index.html
*         │   └── main.js
          ├── node_modules
          │   └── @my-cool-project
          │       └── lib -> ../../../lib
          ├── src
          │   └── index.js
          └── webpack.config.js

Full file contents available in the linked repository, but for convenience I’ll show some excerpts here.

There are two packages in this monorepo: web and lib.

  • lib is a library that exports one function, leftPad.
  • web is a webpage that console.log() a left-padded hello world.

packages/lib/webpack.config.js:

const path = require('path')

module.exports = {
  entry: path.resolve(__dirname, 'src/index.js'),
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    library: 'lib',
    libraryTarget: 'umd'
  },
  mode: 'development'
};

packages/web/webpack.config.js:

const path = require('path')

module.exports = {
  entry: path.resolve(__dirname, 'src/index.js'),
  output: {
    filename: '[name].js',
    publicPath: '/'
  },
  devServer: {
    contentBase: './dist'
  },
  mode: 'development',
  watch: true
};

packages/web/src/index.js:

import { leftPad } from '@my-cool-project/lib'
console.log(leftPad('hello world', 20));

I’ve tried to replicate the important behaviours of a lerna monorepo in a minimalist way.

  • every package has its own directory inside packages
  • lib gets imported, so I’ve given it a package.json
  • all dependencies are hoisted to root-level
    • the only dependency is webpack so this doesn’t really matter
  • web depends on lib via @my-cool-project/lib
    • web has a package-local node_modules with a symlink @my-cool-project/lib that leads to the lib folder
    • it’d be more realistic if I’d hoisted this symlink to root-level, but making it package-local was an easy way to prevent its being clobbered by the npm install

Setup instructions:

# root-level npm install. our only dependencies are the webpack toolchain
npm i
# build lib
cd packages/lib
node ../../node_modules/.bin/webpack
# run the website
cd ../web
node ../../node_modules/.bin/webpack-dev-server

Navigate to http://localhost:8080

In Firefox 80.0b3, you should expect to see the following error when web attempts to import lib:

Uncaught TypeError: __webpack_modules__[moduleId] is undefined
    __webpack_require__ http://localhost:8080/main.js:455
    <anonymous> webpack://lib/./src/index.js?:5
    js webpack:///./node_modules/@my-cool-project/lib/dist/main.js?:28
    __nested_webpack_require_3026__ webpack:///./node_modules/@my-cool-project/lib/dist/main.js?:65
    <anonymous> webpack:///./node_modules/@my-cool-project/lib/dist/main.js?:104
    <anonymous> webpack:///./node_modules/@my-cool-project/lib/dist/main.js?:105
    webpackUniversalModuleDefinition webpack:///./node_modules/@my-cool-project/lib/dist/main.js?:11
    <anonymous> webpack:///./node_modules/@my-cool-project/lib/dist/main.js?:13
    node_modules my-cool-project/lib/dist/main.js@http://localhost:8080/main.js:418
    __webpack_require__ http://localhost:8080/main.js:455
    <anonymous> webpack:///./src/index.js?:2
    js http://localhost:8080/main.js:432
    __webpack_require__ http://localhost:8080/main.js:455
    <anonymous> http://localhost:8080/main.js:529
    <anonymous> http://localhost:8080/main.js:532

In Chrome 84, you’ll get a slightly vaguer message:

Uncaught TypeError: Cannot read property 'call' of undefined
    at __webpack_require__ (main.js:455)
    at eval (index.js:5)
    at Object../src/index.js (main.js:28)
    at __nested_webpack_require_3026__ (main.js:65)
    at eval (main.js:104)
    at eval (main.js:105)
    at webpackUniversalModuleDefinition (main.js:11)
    at eval (main.js:13)
    at Object../node_modules/@my-cool-project/lib/dist/main.js (main.js:418)
    at __webpack_require__ (main.js:455)

What is the expected behavior?

Navigating to http://localhost:8080 should output the following message to the console:

         hello world

I think this may be to do with module federation? lib fails to find its own module, ./src/utils.js. I think it’s looking in the wrong place; it needs to look among its own modules, but it’s looking for them in the top-level __webpack_modules__.

Thanks for any assistance you can provide! 😄

Other relevant information: webpack version: 5.0.0-beta.23 Node.js version: v12.12.0 Operating System: macOS Mojave 10.14.6

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 23
  • Comments: 108 (43 by maintainers)

Commits related to this issue

Most upvoted comments

I was encountering the same problem while migrating my rather complex monorepo to webpack 5. In my case, the problem was due to mixing webpack 4 and 5.

More precisely, it looks like webpack 4 cannot use bundles created by webpack 5 as input. It does not rename the __webpack_require__ function of the inner bundles and passes its own from the outside. The result is that some of the inner modules will use the wrong require function. Webpacdk 5 does a much better job at analyzing scopes and it correctly renames different occurrences of the nested __webpack_require__.

So, it looks like that when we introduce webpack 5 we have to migrate all upstream projects to webpack 5 too.

I got this error when use “externals” in webpack.config.js and there are three scenes:

✅ the first, when use webpack v4 and output commonjs2, it’s running correct

// package.json
{
  ...
  "devDependencies": {
    "webpack": "^4.14.0",
    "webpack-cli": "^3.0.8"
  }
}
// webpack.config.js
module.exports = {
  ...
  output: {
      path: path.resolve(process.cwd(), "lib"),
      filename: "[name].js",
      libraryTarget: 'commonjs2'
  },
  externals: ["vue"],
}

✅ the second, when use webpack v5 and output umd, it’s running correct

// package.json
{
  ...
  "devDependencies": {
    "webpack": "^5.47.1",
    "webpack-cli": "^4.7.2"
  }
}
// webpack.config.js
module.exports = {
  ...
  output: {
    path: path.resolve(process.cwd(), "lib"),
    filename: "[name].js",
    library: {
      type: "umd"
    }
  },
  externals: ["vue"],
}

❌ the third, when use webpack v5 and output commonjs2, it’s running wrong

// package.json
{
  ...
  "devDependencies": {
    "webpack": "^5.47.1",
    "webpack-cli": "^4.7.2"
  }
}
// webpack.config.js
module.exports = {
  ...
  output: {
    path: path.resolve(process.cwd(), "lib"),
    filename: "[name].js",
    library: {
      type: "commonjs2"
    }
  },
  externals: ["vue"],
}

image image

in the procedure, the moduleId will get value the Vue package actually installed path. But the __webpack_modules__[moduleId] is not a function

image

This seem to be related to the eval devtool. webpack can’t rewrite __webpack_require__ inside of eval calls. We might only need to rewrite __webpack_require__ when really needed, but to be honest you shouldn’t nested webpack bundles anyway.

Thanks @evilebottnawi for looking into this, and for recommending to try out the latest fixes in Webpack 5.4.0.

I’ve reproduced in Webpack 5.4.0 without webpack-dev-server. Different error message, though:

Uncaught TypeError: __webpack_require__.r is not a function
    <anonymous> webpack://lib/./src/index.js?:1
    js file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    __nested_webpack_require_3051__ file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    factory file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    factory file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    247 file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    __webpack_require__ file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    <anonymous> file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    <anonymous> file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2
    <anonymous> file:///Users/birch/git/webpack-repro-2/web/dist/main.js:2

The problem arises when importing a library built using eval devtool (e.g. the default for mode: 'development').

@PenguinDetective Found a problem - HMR, because HMR uses __webpack_require__ to provide hot module replacement feature, we have conflicts with external modules, in my-app you import react/react-dom as normal packages, but in my-lib, you use them as externals, if you comment externals in your library, all works fine (but it is can be problem too, it is just for example of the problem).

Here double bundling problem which lead to runtime problems:

  1. You bundle my-lib, so after bundling for react/react-dom packages you have:
/***/ "react":
/*!************************!*\
  !*** external "react" ***!
  \************************/
/***/ ((module) => {

module.exports = require("react");

/***/ })
  1. Then you bundle my-app, webpack in my-app found require("react") and bundle it then rewrite it to:
module.exports = __webpack_require__(/*! react */ "../my-lib/node_modules/react/index.js");

But put found modules inside webpack v4 runtime (i.e. runtime code generated by webpack 4), so library bundled with webpack v5 just can’t found it in own __webpack_modules__ and you see __webpack_modules__[moduleId] is undefined, i.e. webpack v5 runtime in your library tries to import react (i.e. ../my-lib/node_modules/react/index.js), but no this module in __webpack_modules__ for webpack v5 runtime.

Honestly, I don’t think that this will be a problem only for webpack, it will happen for all bundlers, rollup allow to avoid it only because allows to generate libraries without runtime code - i.e. rewrite require/module.exports/import/export/etc on corresponding module system provided by your configuration with https://rollupjs.org/guide/en/#outputpreservemodules.

We can mark react/react-dom as externals for my-app and my-lib for development mode (but CRA doesn’t allow to customize configurations), and we can do versa vice in theory (but it can be problem too with different versions of react/react-dom and two react in your bundle).

I think better solution is not bundling libraries at all as I write library code in ESM. I found some very dirty solutions, but better do not use them, because they can be unstable and lead to other problems if you don’t have deep knowledgeable how webpack works (and they look like monkey patching, that is very bad too).

@sokra thanks for taking the time to have a look at this issue.

you shouldn’t nested webpack bundles

does that mean that webpack 5 no longer supports importing libraries made by webpack? this same example works in webpack 4.

@martinstark

Is a solution possible from webpack’s side, for example by introducing a standardised way where externals are shared between major webpack versions?

I think no, the main problem - we need handle webpack generated code, i.e. __webpack_require__/etc as dependency (like import/require/etc) and rewrite runtime logic, it is very very difficult, it is also worth saying that runtime generation can be changed due bugs/new features between v5.0.0l-latest, same for webpack v4, webpack v3, etc, and we would have to store all the possibilities and handle them, as you can understand it is more impossible than possible

@PenguinDetective

However, when i include CSS, Sass, Sass Modules and other assets to the library, I can’t figure out how to get my head around it without using a bundler.

Yep, it is a problem… for other assets, you can use new URL(...) and load them by URL, it should be supported by many bundlers. You can change component API and load styles on application side and pass classes to your components (maybe this will even allow them to be better composited), but it requires rewrite code

That would be appreciated and your effort would not be wasted.

On Mon, Dec 13, 2021, 6:08 AM Alexander Akait @.***> wrote:

@PenguinDetective https://github.com/PenguinDetective I think we should provide solution in this case anyway, unfortunately some developer find it rather difficult to migrate, so I would like to offer a quick solution and tell you about it so that developer can easily migrate

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/webpack/webpack/issues/11277#issuecomment-992352360, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABMCUB25V6XOJ2KVS2U3MHLUQXH3TANCNFSM4PU4VKCQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You should not apply ModuleConcatenationPlugin plugin directly, you need use optimization options, double usage ModuleConcatenationPlugin can break code

This happened as a result of using a dev bundle on my client library.

@sokra It would be great to continue supporting using webpack to compile libraries, because these libraries can use loaders that the importing codebase doesn’t need.

I tried to follow the tips here to use webpack 5 to reuse microfronts but without success, please if there is a solution let me know: ` new ModuleFederationPlugin({ name: ‘home’, remotes: { home: “home@http://localhost:8080/remoteEntry.js” }, and new ModuleFederationPlugin({ name: ‘home2’, remotes: { home: “home@http://localhost:8080/js/bundle-home-2fba12573fb1d1edabf5.js” },

` Error: “webpack_modules[moduleId] is not a function”

webpack v5 supports library creation, the problem here - double bundling, webpack generates extra runtime code when bundle library, but when you bundle your application you consume already bundled library, now you have two runtimes, unfortunately they are different between webpack version.

So in fact, this reads like “supports library creation, but not really, as it won’t work as soon as a webpack-based application wants to use your library”.

I think this could be explained with a warning somewhere in https://webpack.js.org/configuration/output/#outputlibrary .

For example, I just spent a few hours configuring webpack to bundle my library (it’s a set of React-based components bundled with CSS files, that are loaded separately to js files), only to learn later on from this discussion here, that webpack isn’t be sufficient for my scenario [of bundling a JS+CSS library]. (I wanted to bundle both JS and CSS library files with webpack. In the end, I achieved what I wanted by bundling CSS files with webpack, and JS files separately using tsc.)

Do I understand the thing correctly? (There’s no way to bundle a JS library using webpack5, so that it can be used by both webpack4/webpack5-based applications.) Would you be open to accepting a PR to the docs adding a warning about it? @alexander-akait

@PenguinDetective

There are a lot of problems with CRA too in this case, if you have raw configuration, we can setup it better and avoid these problems… In webpack v5 we have https://webpack.js.org/configuration/output/#outputuniquename, so if you will use webpack v5, you runtime will be unique, so in future you should not get these problems, but there is webpack v4…

Anyway give me time, I will look at this more deeply and try to search solution…

webpack v5 supports library creation, the problem here - double bundling, webpack generates extra runtime code when bundle library, but when you bundle your application you consume already bundled library, now you have two runtimes, unfortunately they are different between webpack version.

You can bundle library in ESM format to reconsume, but I recommend to avoid bundling library at all, Node.js already supports ESM, so if somebody will consume your library and need supporting old browsers, they are transpile and bundle your library on application side.

This incompatibility is very counterintuitive in terms of logic. When output AMD format, developers generally assume that the output will be AMD format only, or at least webpack runtime transparent to developers. but the current webpack runtime incompatibility issue forces developers to care about webpack runtime version, and also require that the libraries must use upgraded webpack (for third-party libraries or old libraries this is often difficult).

Back to the days of webpack2 it was common to use webpack to export AMD packages, and even now it makes sense to expect projects and libraries to share a common build system(we do expect webpack5 to support esm format for a long time and thanks to developers’ hard work there is now experimental support). Most of CLIs like vue-cli still suport export AMD packages today.

Although it doesn’t matter if this issue is not fixed, because the UMD format is working fine😀

Here is the link where they say libraries are supported but not recommended.

https://github.com/webpack/webpack/issues/11277#issuecomment-671039316

On Sun, Dec 12, 2021, 5:11 AM PenguinDetective @.***> wrote:

@alexander-akait https://github.com/alexander-akait - update webpack to v5 for all projects or downgrade to webpack v4 for all projects, you can’t use both versions, because they generated different runtime.

Well, this is something that i would never have figured out on my own, thanks.

@alexander-akait https://github.com/alexander-akait - webpack generates extra runtime code

When you talk in context of “runtime” in webpack, does that mean running webpack in --mode=development ? Because bundling the library once in --mode=production seems to work (which i guess would be named “compilation time”) between running the app (which uses webpack 4) and the one time library build (which uses webpack 5).

@alexander-akait https://github.com/alexander-akait - now you have two runtimes, unfortunately they are different between webpack version.

Is this something that one can expect for even future webpack releases? E.g. v5 and v6.

@alexander-akait https://github.com/alexander-akait - You can bundle library in ESM format to reconsume, but I recommend to avoid bundling library at all, Node.js already supports ESM, so if somebody will consume your library and need supporting old browsers, they are transpile and bundle your library on application side.

Wouldn’t that be an anti-pattern/uncommon to ship a library with the source folder and not the bundled version of it? E.g. running my-app locally and bundling the application with webpack 4 seems to work with your above statement. However then when running my-app straight in the browser and importing dependencies with <script src=" ***@***.***/umd/react.development.js"></script>, then it wouldn’t work anymore. Eventough as you mentioned, you would then transpile your code (e.g. with babel), it would still make a lot of sense to use a bundler to reduce dependency size.

But i have to thank you a lot @alexander-akait https://github.com/alexander-akait and big shoutout to you for all the extra work you have put in to help regarding this issue/and my specific issue. I appreciate your time a lot! ❤️

@longlostbro https://github.com/longlostbro - I was told webpack 5 doesn’t support making libraries. Is that no longer true?

Where did you hear this? A common saying is that “use webpack for applications and rollup for libraries”, but i never heard that webpack doesn’t support making libraries. Also, PSA, i tried to use rollup instead of webpack and while it does work/solve the problem, you’d need to add many third party plugins, just like with webpack, but the community is smaller and some third party libraries that i had to use to reproduce the same results maybe had like 10 stars on github. Not saying that i don’t trust them, it’s just that i’m worried for future support and i try to avoid changing every quartal the bundler just because of XYZ issue or missing support for XYZ feature.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/webpack/webpack/issues/11277#issuecomment-991869458, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABMCUBYHARDPODSO7KEXW6TUQRYMPANCNFSM4PU4VKCQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

@PenguinDetective You have two webpack versions, webpack v5 in my-lib and webpack v4 in my-app, only webpack v5 allow to rewrite own generated code (i.e. rewrite already bundled code), you can’t use the same for webpack v4, in your case you have runtime code from webpack v4 and runtime code from webpack v5, so you got __webpack_modules__[moduleId], because there are two webpack runtime function on the one page.

Solution - update webpack to v5 for all projects or downgrade to webpack v4 for all projects, you can’t use both versions, because they generated different runtime.

Thanks, I will at this in near future

facing the same issue

below is in libraries bundled with Webpack 5

// EXTERNAL MODULE: external {"commonjs":"react","commonjs2":"react","root":"React"}
var external_commonjs_react_commonjs2_react_root_React_ = __webpack_require__(3701);

...


/***/ 3701:
/***/ (function(module) {

"use strict";
module.exports = require("react");

/***/ }),

but webpack5 will transform code like below

/***/ 3701:
/***/ (function(module) {

"use strict";
module.exports = require("./node_modules/react/index.js");

/***/ }),

it will throw error for module not found

E.g. for debug/development purposes: you can compile a library in dev/watch mode with output into /node_modules/library of a host codebase

one can still compile in dev/watch mode using different from eval-* devtool, no? There’re quite a few of them: https://webpack.js.org/configuration/devtool/#devtool This issue exists only when eval is used.

Hi, I do have the exact same issue (lerna monorepo+libraries) and I’m looking for a workaround, any lead?

And/or is there an estimated ETA? I mean, should I hope to use webpack 5 soon (I really love the “dependsOn” on feature, it’s a marvel!) or wait a few months that the team had time to fix this issue?

Best regards and thanks a lot for this incredible tool 😃

Raw source if JavaScript in stage >= 4. Transpiled source if Typescript or any other language. There is no specced solution for styles yet, but all tools understand importing css. Transpile it to css if in a different language. Best publish a ESM, but CommonJs is fine too. To usage in node.js publish both. You can bundle as ESM e. g. via rollup but this breaks/hinders some optimizations like sideEffects-flag or splitChunk, but has benefits for application build time. Minimizing is an application-level concern and I wouldn’t ship my library minimized. It’s also difficult to debug. But it has benefits to application build time.