tooling.report

feature

ECMAScript modules

Can ECMAScript modules bundles be generated?

Person in shorts with blue hair walking left

Introduction

ECMAScript modules are supported in all modern browsers, representing more than 90% of web traffic. ECMAScript modules are a fast, lightweight way to load scripts without the need for a custom loader. Modules are also always executed asynchronously and in strict mode, improving performance and helping surface otherwise hidden errors.

In addition to widespread browser support, ECMASCript Modules are supported in Node.js 12+. This makes them a great choice for portable JavaScript that needs to be able to run in any environment.

The Test

This test bundles two entry modules, index.js and profile.js. Each depends on a method imported from a shared utils.js module, and index.js dynamically imports a fourth module which should create a split point.

index.js

import { logCaps } from './utils.js';

async function main() {
  const { exclaim } = await import('./exclaim.js');
  logCaps(exclaim('This is index'));
}
main();

profile.js

import { logCaps } from './utils.js';
logCaps('This is profile!');

exclaim.js

export function exclaim(msg) {
  return msg + '!';
}

utils.js

export function logCaps(msg) {
  console.log(msg.toUpperCase());
}

The output of this test should be four bundles in ECMAScript Modules format. Two entry bundles corresponding to the two entry modules, a code-splitted utils.js module, and a fourth bundle containing exclaim.js that is loaded via dynamic import().

Conclusion

browserify

Browserify does not support es-modules output (out of scope for the project).

Issues

  • N/A
parcel

Parcel lets you set targets in your package.json to influence how your project is built, including an 'esmodule' setting.

This will change the target browsers to the ones that support ECMAScript modules, but that doesn't include browsers that support dynamic import(). By default Parcel will include a polyfill, unless you set the browserslist to browsers that support import().

However, Parcel will duplicate modules that are imported by multiple entry points. If those modules contain state, which is common for caching, counters, bookkeeping etc, then that state will become out of sync.

Issues

rollup

ESM is Rollup's most natural output format.

webpack

Webpack does not support outputting native JavaScript Modules. Webpack 5 has begun to make changes that would potentially support this, available behind an experimental flag.