External imports in ESM output are two layers of "default" deep
See original GitHub issueBug report
What is the current behavior?
Relevant parts of config:
experiments: { "outputModule": true },
externalsType: "module",
externals: {
"fela-plugin-named-keys": "fela-plugin-named-keys"
},
When I have set my Webpack config to output ESM modules for use in a Node.js project, and I have made a certain module an “external” module to be imported by Node.js during runtime, the code Webpack has generated is causing this import to be of this structure:
{
"default": {
"default: () => {
// This function is an example of whatever is the value of the default
// export of this module, 'module.exports = ...' OR 'export default ...'
}
}
}
If I have used an import in my code like so (which worked perfectly fine before when I was using commonjs as a target):
import namedKeys from "fela-plugin-named-keys";
const namedKeysPlugin = namedKeys();
The code being generated from this, seems perfectly fine on first glance:
var namedKeysPlugin = (0,external_fela_plugin_named_keys_namespaceObject.default)();
But we end up having an error thrown that looks like this:
TypeError: fela_plugin_named_keys__WEBPACK_IMPORTED_MODULE_5__.default is not a function
If I put in a console.log(namedKeys)
, it reveals to us that the problem seems to be that the code for some reason is making this import a module structure that’s two layers deep:
console.log(external_fela_plugin_named_keys_namespaceObject.default);
// Output in console:
// { default: [Function: namedKeys] }
If the current behavior is a bug, please provide the steps to reproduce.
I’ve created a github repo with a replication of this happening: https://github.com/lostpebble/webpack-esm-import-problem
There are steps to reproduce in the Readme.
What is the expected behavior?
Default exports are imported correctly only a single layer deep in the structure of:
{
default: () => {
// Example of default export value
}
}
Other relevant information: webpack version: ^5.51.1 Node.js version: 16.7.0 Operating System: Windows 10 Additional tools:
Observations
When I manually edited the output file, from this:
import * as __WEBPACK_EXTERNAL_MODULE_null__ from "fela-plugin-named-keys";
to this:
import __WEBPACK_EXTERNAL_MODULE_null__ from "fela-plugin-named-keys";
It worked. I see that pretty much all imports are done in this way * as WHATEVER from "whatever"
when we make use of externalsType: "module"
externals. So perhaps this is where the problem lies?
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (3 by maintainers)
Top GitHub Comments
@sokra - but most modules these days still don’t expose an ESM entry point as they are still commonjs in their output. But on the flip side the modules that are pure ESM are not compatible without having your project use ESM (because
require
does not work for them)… 🤔 So, I’ve decided to try and move my project over to ESM because clearly certain large modules are heading this way now. (There is a very intense discussion about this over here: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).I have no control over
fela-plugin-named-keys
and the 100s of other modules like it in my dependency graph (I just used it here as an example because it was the first one to cause issues for me).This is a bit of a jarring experience- as I would expect Webpack to figure out a way to use these modules correctly, as they worked just fine before when our project made use of commonjs.
Also- for this module
fela-plugin-named-keys
, Webpack is actually using its ESM file as the source (/es/index.js
) because this has been set inpackage.json
("module": "es/index.js", "jsnext:main": "es/index.js"
)- which clearly defines the default export that is expected… So surely this should be working just fine then?Another thing which perhaps warrants a different issue, but I noticed as I was playing with this and trying to get it to work, is that when I change my Webpack config from
mode: "development"
tomode: "production"
, Webpack does not output external module imports correctly anymore- they all become a single:instead of
And hence only the last imported module “wins” and becomes the WEBPACK_EXTERNAL_MODULE_null import which is then used (incorrectly) everywhere.
Issue was closed because of inactivity.
If you think this is still a valid issue, please file a new issue with additional information.