Skip to content

nktnet1/esm-sync

Repository files navigation

esm-sync

This is a fork of esm: the brilliantly simple, babel-less, bundle-less ECMAScript module loader (which is now unmaintained).

This fork includes:

  • Assorted updates from @httptoolkit/esm and esm-wallaby fork, adding support for ES modules containing new ES syntax, supporting modern Node versions (at least up to v22), and supporting node:* imports.
  • Support for modules that use the const require = createRequire(...) pattern (or declare any other global require variable) which are otherwise unusable with esm.
  • Support for modules that use only an exports map in their package.json, without a main field, which are otherwise unresolvable (reporting "Cannot find module", even though import() works correctly).
  • Built-in types for use in TypeScript projects

This package is maintained for use in the import-sync project.

You may also be interested in jiti, which provides legacy (deprecated, but still reliable) support for synchronous imports.

Install

npm install esm-sync

Getting started

There are two ways to enable esm-sync.

  1. Enable esm-sync for packages:

    Use esm-sync to load the main ES module and export it as CommonJS.

    index.js

    // Set options as a parameter, environment variable, or rc file.
    require = require("esm-sync")(module/*, options*/)
    module.exports = require("./main.js")

    main.js

    // ESM syntax is supported.
    export {}
  2. Enable esm-sync for local runs:

    node -r esm-sync main.js

    💡 Omit the filename to enable esm-sync in the REPL.

Features

👏 By default, 💯 percent CJS interoperability is enabled so you can get stuff done.
🔒 .mjs files are limited to basic functionality without support for esm-sync options.

Out of the box esm-sync just works, no configuration necessary, and supports:

Options

Specify options with one of the following:

  • "esm" field in package.json
  • CJS/ESM in an .esmrc.js, .esmrc.cjs, or .esmrc.mjs file
  • JSON6 in an .esmrc or .esmrc.json file
  • JSON6 or file path in the ESM_OPTIONS environment variable
  • ESM_DISABLE_CACHE environment variable
{
"cjs":true

A boolean or object for toggling CJS features in ESM.

Features
{
"cache":true

A boolean for storing ES modules in require.cache.

"esModule":true

A boolean for __esModule interoperability.

"extensions":true

A boolean for respecting require.extensions in ESM.

"mutableNamespace":true

A boolean for mutable namespace objects.

"namedExports":true

A boolean for importing named exports of CJS modules.

"paths":true

A boolean for following CJS path rules in ESM.

"vars":true

A boolean for __dirname, __filename, and require in ESM.

"dedefault":false

A boolean for requiring ES modules without the dangling require().default.

"topLevelReturn":false

A boolean for top-level return support.

}
"mainFields":["main"]

An array of fields checked when importing a package.

"mode":"auto"

A string mode:

  • "auto" detect files with import, import.meta, export,
    "use module", or .mjs as ESM.
  • "all" files besides those with "use script" or .cjs are treated as ESM.
  • "strict" to treat only .mjs files as ESM.
"await":false

A boolean for top-level await in modules without ESM exports. (Node 10+)

"force":false

A boolean to apply these options to all module loads.

"wasm":false

A boolean for WebAssembly module support. (Node 8+)

}

DevOpts

{
"cache":true

A boolean for toggling cache creation or a cache directory path.

"sourceMap":false

A boolean for including inline source maps.

}

Tips

Bundling

  • For bundlers like browserify+esmify, parcel-bundler, and webpack add a "module" field to package.json pointing to the main ES module.

    "main": "index.js",
    "module": "main.js"

    💡 This is automagically done with npm init esm or yarn create esm.

Extensions

Loading

  • Load esm-sync before loaders/monitors like @babel/register, newrelic, sqreen, and ts-node.

  • Load esm-sync for jasmine using the "helpers" field in jasmine.json:

    "helpers": [
      "node_modules/esm-sync"
    ]
  • Load esm-sync with “node-args" options of:

    • pm2: --node-args="-r esm-sync"
  • Load esm-sync with “require” options of ava, mocha, nodemon, nyc, qunit, tape, and webpack.

    💡 Builtin require cannot sideload .mjs files. However, .js files can be sideloaded or .mjs files may be loaded with dynamic import.