nodejs esm module output bundling lacks module prototype for externals · Issue #7446 · webpack/webpack.js.org (original) (raw)
Bug report
What is the current behavior?
For my electron app I want to bundle the nodejs code of my main thread because of a) typescript and b) performance optimizations. That means I have "type": "module"
, regular node 20+ esm style code and want to bundle my dependencies into a final bundle (as I ship this bundle with my electron executable and not as part of a backend that has a node_modules dir).
To achieve a clean esm bundle (without createRequire and with support for dynamic imports) I use:
- target: "es2022"
- define standard node modules as externals
- use experiments.outModule: true
- output.chunkFormat: "module"
- and module: true
I now want to bundle in the jimp
library that has the pngjs
dependency, which uses an util.inherits()
call onto node-native stream
in their chunkstream.js
file:
https://github.com/pngjs/pngjs/blob/c565210c602527eb459f857eeb78183997482d5b/lib/chunkstream.js#L18
It looks like this in the bundle:
let Stream = webpack_require(/*! stream */ "stream"); util.inherits(ChunkStream, Stream);
Now the issue is that util.inherits expects stream
to have a prototype and errors like so when run:
node:util:290 throw new ERR_INVALID_ARG_TYPE('superCtor.prototype', ^
TypeError [ERR_INVALID_ARG_TYPE]: The "superCtor.prototype" property must be of type object. Received undefined at Module.inherits (node:util:290:11) at ./node_modules/pngjs/lib/chunkstream.js (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:15981:6) at webpack_require (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:45536:41) at ./node_modules/pngjs/lib/parser-async.js (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:17191:19) at webpack_require (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:45536:41) at ./node_modules/pngjs/lib/png.js (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:17814:14) at webpack_require (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:45536:41) at ./node_modules/@jimp/js-png/dist/esm/index.js (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:31862:63) at webpack_require (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:45536:41) at ./node_modules/jimp/dist/esm/index.js (file:///Users/myname/dev/jimp-nodenext/main.bundle.dev.js:39797:70) { code: 'ERR_INVALID_ARG_TYPE' }
When I edit the bundle, manually logging Stream.prototype
yields undefined
, and logging Stream
yields:
[Module: null prototype] {
Duplex: [Function: Duplex] {
fromWeb: [Function (anonymous)],
toWeb: [Function (anonymous)],
from: [Function (anonymous)]
},
PassThrough: [Function: PassThrough],
Readable: [Function: Readable] {
ReadableState: [Function: ReadableState],
_fromList: [Function: fromList],
from: [Function (anonymous)],
fromWeb: [Function (anonymous)],
toWeb: [Function (anonymous)],
wrap: [Function (anonymous)]
},
...
I'm assuming the prototype that util.inherit
expects got lost during webpacks bundling.
If the current behavior is a bug, please provide the steps to reproduce.
Here's a minimal repo for reproduction: https://github.com/tom2strobl/webpack-jimp-nodenext
See for additional comments regarding the webpack configuration: https://github.com/tom2strobl/webpack-jimp-nodenext/blob/main/webpack.config.js
What is the expected behavior?
webpack to bundle in a way that standard node modules that are defined as external retain their original prototypes for util.inherits
compatibility.
Other relevant information:
webpack version: 5.95
Node.js version: 20.17
Operating System: macOS 15.0.1
Additional tools: jimp 1.6.0 / pngjs 7.0.0