Transpilers
Transpilers convert code from and to a specific ES version. Do not use more than one unless you have a specific need to do so.
Microsoft Typescript
Targets a specific ES version. Setting the 'dom' lib adds definitions like window and document.
Babel
Targets a specific ES version. With '@babel/preset-env' the target can be a browser list like 'last 2 versions, not dead'
Module specifications
Before the release of NodeJs/CommonJS in 2009 it was hard to write modular
Javascript. For HTML, the best option was using multiple <script>
tags.
Without HTML modular Javascript did not exist.
Anno 2021 many module specifications exist. The two most used are CommonJS and ES Modules (ESM). Worth looking at is also the universal specification called UMD.
CommonJS
CommonJS uses 'require' for importing and 'module.exports' for exporting.
This is the module specification used by NodeJS. Not supported by browsers. Biggest disadvantage is that 'tree shaking' is impossible.
EcmaScript Modules (ESM)
ESM uses 'import' for importing and 'export' for exporting.
This is the module specification added to the Javascript language since ES6. Besides being language native, it allows for 'tree shaking'.
Being native Javascript it is supported by modern browsers: chrome 61+, firefox 60+, safari 10.1+, edge 16+.
UMD
The UMD (Universal Module Definition) specification allows for importing from different module loaders like CommonJS and AMD.
UMD uses an IIFE (Immediately-Invoked Function Expression) which looks for a module specification. When found, the module is setup accordingly. Without a specification the module is globally set.
Bundles
Browsers bundles
Since 2017 modern browsers can load ESM by using <script type="module">
. This
makes bundling code easier but bundling is still required. This is because
sending your code to the browser in one request is more efficient than by using
multiple requests.
Module bundles
Module bundles are different from browser bundles in that they are not executed on load. Using a module system, a part of the module can be used. With e.g. CommonJS a function can be loaded with 'require' and then executed later.
When a module is intended for browser use, a module cannot 'import' from another module. This is because once the code runs in the browser, the browser has no way of knowing where the module to import lives.
Future solutions will solve this by importing from full repository urls.
Bundlers
The four most used bundlers are Browserify, Webpack, Parcel and Rollup. They originated solving different problems, but evolved to be very much alike.
Bundlers are configured to transpile using Babel or Typescript and are setup to creates either a 'module' or a 'browser' bundle.
Browserify (2013)
Make Node modules run in the browser. Browserify lets you require('modules') in the browser by bundling up all of your dependencies.
Webpack (2014)
Create a dependency graph for all of the assets in a website. Then create modules from the graph and bundle everything into one Javascript file.
Anno 2021 Webpack does not bundle ESM into one file.
Parcel (2017)
A faster alternative for Browserify and Webpack with zero configuration.
Rollup (2018)
Compile small pieces of code into a library. As opposed to Webpack, Rollup uses ESM to create bundles and thus can bundle ESM.
ES with Gatsby and NextJs
Using products like Gatsby and NextJs, what version of ES should you use? Both use Babel and Typescript to transpile and both use Webpack to create a bundle. This means you can write your code in EsNext and Typescript.
Configuring Gatsby and NextJs is hard because you need to know which transpiler does what. Adding Webpack to the mix does not make it easier.
Someday, Gatsby and Nextjs might default to Typescript and modules can be loaded by using full url's.
Using node modules from the NPM repository things become even harder to grasp. Gatsby and NextJs create bundles that target the browser. This means that node modules must work in the browser. The browser?
Modern browsers support ES6+ and ESM. Old browsers do not. This is why things like 'browserslist' exist.
Because of the current (2021) default bundler configuration of Gatsby and NextJs this is how you should create a node module that works with Gatsby and NextJs:
- transpile to ES5 (use typescript, not babel)
- bundle into one file (use rollup, not webpack)
- React anno 2020 is distributed in UMD, therefore use CommonJS, not ESM
More on this in this article.