I’ve recently run into a bit of a frustrating situation trying to provide ESM build of libraries along-side commonjs ones. Ideally the ESM code should always be used by webpack, and allow cherry picking modules (as to not have to rely solely on treeshaking).
Currently, with the strictness of importing none mjs files into .mjs
we can’t compile the same codebase in a way that works as cjs or esm modules. take the following example:
_MyComponent.mjs
import { polyfill } from 'react-lifecycle-compat';
// use polyfill(Component) etc.
react-lifecycle-compat
exposes both a esm build (.js
) and a cjs file here (compiled esm -> cjs)
What I want to do is compile MyComponent.mjs with babel to MyComponent.js and ship both files, relying on webpack to resolve the .mjs
file before the .js
one. However this won’t work.
react-lifecycle-compat
is not.mjs
so webpack considers it not an esm file and requires i write the import as:import ReactLifeCycleCompat from 'react-lifecycle-compat';
,- Compiling this to cjs will also break, because of
react-lifecycle-compat
‘s__esmodule
flag, so I can’t import that as a default because babel sees taht it’s only named exports.
TL: DR;
Consuming compiled, __esmodule
flagged, modules with name exports cannot be written in a way that satisfies both cjs and mjs consumers.
I realize I can configure webpack to treat mjs
as javascript/auto
but that’s not ideal, because I’m interested in providing libraries that can be consumed by webpack and node witthout requiring users to configure something, while also wanting to move towards future standards and take advantage of esm optimizations
Ah, so this is because of third-party deps which use .mjs. They really shouldn’t be jumping on board that soon either. However, you can override the webpack config for this…