---
title: ES模块与Tree Shaking
category: JavaScript
---

## ES Modules & CommonJS & AMD

* JavaScript doesn't come with a module solution by default
* but the community came up with lots of specifications and implementations
  * Common Specs are CommonJs, AMD
  * NodeJS implements the CommonJS spec, RequireJS implements the AMD spec
* but they came with cons:
  * CommonJS: hard to analyse/tree-shaking (due to dynamic loading), no async loading support, not supported in browser
  * AMD: hard to analyse/tree-shaking (due to dynamic loading), not ideal async syntax
* and here comes the cure: ES Modules. It's in the ES6 spec to JavaScript (finally)... 
* it solves many headaches: static analyzing / tree-shaking, elegant syntax, async loading (with loader support)
* .. however, it's not supported by default everywhere
  * transpiler (Babel etc) are made to transform ES6 imports / exports to ES5 requires in NodeJS
  * bundlers (Webpack etc) are made to transform ES6 imports / exports to ES5 requires and bundle them for browsers
* and what is .mjs and .cjs then?
  * so after NodeJS v14 the ES modules are supported out of the box, just V8 need to know how to parse ES module files, so
    * to explicitly use this feature, change the file extension to .mjs should work
    * to implicitly use this feature, specify "type": "module" in package.json
  * and browsers started to support ES modules via <script type="module" src="app.js">
* but it's basically only file extension change, why does it support static analyzing / tree shaking all of a sudden?
  * because in old way of writing import/export, we're relying on transpilers to transform code into ES5 compatible one, which is eventually imported via the "require()" API in NodeJS, and that's why static analyzing is not possible since require() is dynamic in its nature
