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 thatconsole.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 apackage.json
- all dependencies are hoisted to root-level
- the only dependency is webpack so this doesn’t really matter
web
depends onlib
via@my-cool-project/lib
web
has a package-local node_modules with a symlink@my-cool-project/lib
that leads to thelib
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)
Links to this issue
Commits related to this issue
- avoid unnecessary replacement of `__webpack_require__` when nesting bundles avoid wrapping externals in the eval() as this breaks nesting bundles fixes #11277 fixes #12300 — committed to webpack/webpack by sokra 3 years ago
- Add unique output name to webpack output config Correct conflicts with webpack runtimes (ie when including widget in a host webpack project). [Discussed in detail here](https://github.com/webpack/we... — committed to Matt-Jensen/Next-widget by Matt-Jensen 2 years ago
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 outputcommonjs2
, it’s running correct✅ the second, when use
webpack v5
and outputumd
, it’s running correct❌ the third, when use
webpack v5
and outputcommonjs2
, it’s running wrongin the procedure, the
moduleId
will get value theVue
package actually installed path. But the__webpack_modules__[moduleId]
is not a functionThis seem to be related to the
eval
devtool. webpack can’t rewrite__webpack_require__
inside ofeval
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:The problem arises when importing a library built using
eval
devtool (e.g. the default formode: 'development'
).@PenguinDetective Found a problem - HMR, because HMR uses
__webpack_require__
to provide hot module replacement feature, we have conflicts with external modules, inmy-app
you importreact
/react-dom
as normal packages, but inmy-lib
, you use them as externals, if you commentexternals
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:
my-lib
, so after bundling forreact
/react-dom
packages you have:my-app
, webpack inmy-app
foundrequire("react")
and bundle it then rewrite it to: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 importreact
(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 formy-app
andmy-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 ofreact
/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.
does that mean that webpack 5 no longer supports importing libraries made by webpack? this same example works in webpack 4.
@martinstark
I think no, the main problem - we need handle webpack generated code, i.e.
__webpack_require__
/etc as dependency (likeimport
/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
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 codeThat would be appreciated and your effort would not be wasted.
On Mon, Dec 13, 2021, 6:08 AM Alexander Akait @.***> wrote:
You should not apply
ModuleConcatenationPlugin
plugin directly, you need useoptimization
options, double usageModuleConcatenationPlugin
can break codeThis 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”
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…
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:
@PenguinDetective You have two webpack versions, webpack v5 in
my-lib
and webpack v4 inmy-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
but webpack5 will transform code like below
it will throw error for module not found
@Haraldson in this case your problem is https://github.com/webpack/webpack/issues/12964 😄
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.