preface

The classic interview question is “The Difference between common.js and ES Module”, which many people can recite fluently.

Commonjs

  • CommonJs can load statements dynamically, with code occurring at run time
  • CommonJs export value is a copy, it is not easy to check variable pollution

ES Module (hereafter referred to as ESM)

  • The ESM is static and the code happens at compile time
  • An ESM export is a reference to the CommonJs and Es modules, and the values are readable and cannot be modified

Esm is the future of JavaScript modularity. Because it solves the problem of variable contamination, code maintenance, code dependency. It makes your code more scientific. This is why deno uses ESM by default.

Getting back to the point, how can we run ESM code directly on Nodejs or in a browser is an interesting and practical question.

How is this allowed in the Nodejs environment

1. Run the ESM using a compilation tool

The most common way is to use Babel with packaging tools such as WebPack. With the popularity of WebPack and Vue, these tools seem to be standard, but the disadvantage of WebPack is also obvious, it can make commonJS and ESM mixed, resulting in some code non-standard situation, I believe this situation is common in business code. It also exists in well-known third-party component libraries such as ANTD3.

Rollup, on the other hand, is compiled based on ES6 syntactical specifications, and is lightweight and compact, making it ideal for packaging NPM libraries. Newer packaging tools, such as ESBuild and SWC, can also implement compilation packaging, even though it is getting faster and faster, but still requires compilation. An important feature of these repositories is the use of ESM syntax.

All of the above tools can be applied to ESM syntax compilation, but there are many projects that do not need to package such time-consuming process of compilation, such as some CLI tools, simple micro services, etc. How to ensure efficient and correct esM code running?

2. Use a third-party library to run the ESM

In the case of earlier Nodejs versions, there are several tools available, including Module Loader and Command Line (CLI).

Module Loader can preload esM packages provided by third parties. From then on, it can be babelless, Bundleless. You can run ESM code directly without using a large compilation tool, as follows.

node -r esm index.js
Copy the code

Similarly, the egoist/ esbuild-Register library can also achieve the effect of Module Loader with the support of ESBuild, and make use of the high performance features of ESbuild to run the code more efficiently.

node -r esbuild-register index.js
Copy the code

The Command Line, based on the packaged CLI, is just another way of doing module pre-processing. Babel-node directly takes advantage of its Babel syntax to run ESM code. Since Babel itself is an implementation of JS, its official documentation also states that it is not recommended for use in production environments and can lead to high memory footprint issues, which are common with such tools.

babel-node index.js
Copy the code

Similarly, ESNO can run ESM code directly from the command line. The principle is based on ESbuild. It is recommended to use this method here. Since ESbuild is implemented by go, it can solve the problem of high memory consumption to a large extent and ensure certain execution performance.

esno index.ts
esmo index.ts
Copy the code

This type of third-party repository is suitable for use in lower nodeJS versions and non-production environments, and they exist for convenience rather than utility and stability. How can I run ESM code efficiently?

3. Run the ESM using Native Nodejs

Node Verison 13.2.0 officially supports ES Modules

It is necessary to use Native Nodejs to run ESM code. Higher versions of Nodejs provide the ability to run ESM directly. Lts14 is recommended. There are two ways to run ESM code:

Json type: “modules” to indicate the type of the module. After that, run Node index.js directly.

// pakage.json{..."type": "modules"
}
Copy the code

In the second case, change the file name to.mjs, indicating that the file is ESM code. The biggest difference between the two approaches is the module scope. The former is the scope of the package, which is declared with the dimension package. The latter takes the file dimension and is not limited to the scope of the package.

How do I run esM in a browser

Browsers differ from Nodejs in that most newer browsers support ESM running. Esm-level code compilation and packaging can significantly reduce package size and resource transfer speed. This is why frameworks like Vite adopt the packaging model of modern browsers (plus legacy compatibility). Adding type=”module” to the SCRIPT tag in HTML indicates that it introduces ESM code. When older browsers don’t support ESM, it reads addresses in the Nomodule script and reads compatible versions of JS code. In this way, it can effectively reduce the js volume of most browsers, and ensure the compatibility of older browsers.

<script type="module" src="dist/index.js"></script>
<script nomodule src="dist/index.legacy.js"></script>
Copy the code

conclusion

Both Nodejs and browser environments now have good Native support for ESM syntax. As front-end engineers, we need to be technologically forward thinking. When writing a repository, should we use typescript, ESM or common.js? Why not embrace the third generation of Javascript by opting for a newer JS runtime environment, see ESM Import and Bundleless.

The resources

Will we be able to use ES Modules in Node in 2020