100% ESM module world - what it mean?

Viewed 277

While reading about tree shaking in webpack documentation, I came across this sentence:

In a 100% ESM module world, identifying side effects is straightforward. However, we aren't there just yet.

What do they mean by "100% ESM module" and how it is different from the current import and export that we already use today?

reference: https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free

2 Answers

The documentation you're reading is contrasting two types of scripts:

  • Scripts which expose everything they do through what they import and export
  • Scripts which do something in addition to importing and exporting (this could be seen as a "side effect")

Consider a big library, one that installs itself as a namespace on the global object to expose its functionality. Let's say that jQuery did this - that is, that it runs something like

const jQuery = (function() {
  // lots and lots of code
})();
export default jQuery;
window.jQuery = jQuery;

This contains a side-effect: the line

window.jQuery = jQuery;

This means that other parts of your application could use window.jQuery without jQuery being specifically imported into that module. For example, you might have

// someModule.js
export const doStuff = () => {
  window.jQuery('div').text('Hi!');
};

And this can work without the line

import jQuery from 'jQuery';

inside the module script, because jQuery is on the window. (For this to work, there needs to be at least one module somewhere that does import 'jQuery'; or something like that, so that jQuery's code that assigns itself to the window runs)

Because of the side-effect, Webpack will have a harder time with automatic tree-shaking - you'll have to explicitly note which modules depend on modules with side-effects.

In contrast, a module without dependency side-effects would be the someModule.js example above: all it does it export a function, without adding or changing functionality elsewhere.

So by "100% ESM module", Webpack is probably referring to scripts for which all modules' dependencies are explicit with import statements, instead of having to depend on side-effects (like a non-imported module assigning something to the window).

There are two popular module syntax nodejs use.

Commonjs: https://nodejs.org/dist/latest-v14.x/docs/api/modules.html

// exporting
module.exports.a = 1
// or, exports is an alias to module.exports, for all differences check out docs
exports.a = 1
// you can assign module.exports object as well, this sets what's exported
module.exports = {
  b: 2
}
// a is not exported anymore


// importing default import, imports module.exports object
const a = require('./b')
// or via named import
const {c} = require('./b');

ES modules: https://nodejs.org/dist/latest-v14.x/docs/api/esm.html

// names export
export const a = 1;

// default export
export default const b = 2;

// importing via name
import {a} from './c'

// importing default export
import c from './b'

Commonjs and esm are still in use. So we are not in %100 esm world yet.

Related