Caution
With much improved ESM-CJS interop support compared to several years ago, as well as improvements to babel and webpack, the major use cases (and major blockers) for this package have thankfully been fixed. Yay! No need to bother with any of the below.
This package exposes a tiny Node.js-only wrapper around the import
function.
This purpose of this wrapper is as syntactic sugar for dynamic imports of
externalized ESM dependencies in TypeScript/ESM
source destined to be bundled as CJS by Webpack. Since this package should
itself be an externalized dependency, using
import-esm-interop
ensures:
- Webpack does not convert the dynamic import into a require statement
- Webpack does not complain about "critical dependencies" that have been properly externalized
- Webpack does not do something catastrophic like blindly bundle all your source files into one massive chunk
Hence, this package has a very niche use case and you probably don't need it. For most packages, it's easier to use their CJS entry point if available. In a decade (🤞🏿) when CJS is dead and buried and ESM reigns supreme, this package will be deprecated.
This package also passes through TypeScript typings if provided.
npm install import-esm-interop
This interop function should only be used in CJS code or code that is compiled down to CJS (such as TypeScript)!
const { importEsm } = require('import-esm-interop');
// Equivalent to (await import('some-lib')).default
const someLib = await importEsm('some-lib');
// Equivalent to the above
const someLib = await importEsm('some-lib', 'default');
// Equivalent to the above, but with TypeScript typings
const someLib = await importEsm<import('some-lib').default>('some-lib');
// Equivalent to (await import('some-lib')).aNamedExport
const aNamedExport = await importEsm('some-lib', 'aNamedExport');
// Equivalent to { bNamedExport: (...).bNamedExport, cNamedExport: ... }
const { bNamedExport, cNamedExport } = await importEsm(
'some-lib',
'bNamedExport',
'cNamedExport'
);
// Equivalent to the above, but with TypeScript typings
const { bNamedExport, cNamedExport } = await importEsm<{
bNamedExport: import('some-lib').bNamedExport,
cNamedExport: import('some-lib').cNamedExport
}>('some-lib', 'bNamedExport', 'cNamedExport');
// Equivalent to await import('some-lib')
const SomeLib = await importEsm('some-lib', '*');
// Equivalent to the above, but with TypeScript typings
const SomeLib = await importEsm<import('some-lib')>('some-lib', '*');
If reusing the same typed import multiple times, you can make things less painful by extracting away the dynamic import into a top-level function. Said function could even be placed in a shared util file somewhere.
For example:
// file: ./vendor-interop.ts
export const importSomeLib = async () => {
return importEsm('some-lib', 'bNamedExport', 'cNamedExport') as {
bNamedExport: import('some-lib').bNamedExport,
cNamedExport: import('some-lib').cNamedExport
};
}
// file: ./index.ts
import { importSomeLib } from './vendor-interop'
export async function doesSomething() {
const { bNamedExport } = await importSomeLib();
bNamedExport();
}
Again, we use importEsm
instead of inlining the dynamic import to avoid
problems with Webpack. If you're not bundling your source, then there is no
need to use this sugar function!
Further documentation can be found under
docs/
.
This is a CJS2 package built for Node14 and above. Due to it
being for CJS<->ESM interop, this package is only available via require(...)
and cannot be imported by ESM code! Further, this package is not meant to be
bundled (and will likely cause an error if it is attempted), and should instead
be externalized along with every other module under
node_modules/
.
For TypeScript and IDEs, each entry point (i.e. ENTRY
) in package.json
's
exports[ENTRY]
object includes an
exports[ENTRY].types
key pointing to its respective
TypeScript declarations file. There may be other keys for other
runtimes as well, including node
and browser
. Finally,
package.json
also includes the
sideEffects
key, which I set to false
by default for
most of my libraries.
New issues and pull requests are always welcome and greatly appreciated! 🤩 Just as well, you can star 🌟 this project to let me know you found it useful! ✊🏿 Thank you!
See CONTRIBUTING.md and SUPPORT.md for more information.