No more transpiling, no more difficulties with import and export
Finally! The latest version of Node.js — v14.0.0 — was introduced on April 22nd, 2020. This update introduced a lot of interesting features, but there was one change we desperately waited for. Node 14 introduces ECMAScript modules — no more transpiling, no more difficulties with import and export. Why we are so excited to share this news and what it means for the JS developer community — I will explain here.
Related services
Node.js Development Services
Spoiler! The recent update, which introduces ECMAScript modules to Node, brought this technology one step closer to isomorphic (or universal) JavaScript. Isomorphic JS is why we believe that JavaScript is the technology of the future: a developer writes code for both client and server sides. It brings efficiency, convenience, and quality.
Keenethics started with Meteor js development. This framework is mainly about Universal JS, and although it was not as successful as React or Angular, it had a profound impact on developers’ thoughts.
Some Background History
JavaScript was introduced as a language for writing small and simple scripts, which would perform separate tasks. For quite some time, JS existed as such, perfectly performed its purpose, and thus, had no language-level module system. Yet, the scripts inevitably grew more and more complex — so the need to organize code into modules appeared.
The community developed various systems to meet this goal: AMD, CommonJS, UMD, and ECMAScript modules.
- AMD (Asynchronous Module Definition) is one of the most ancient module systems, which was initially implemented with the means of require.js library.
- UMD (Universal Module Definition) is a module system introduced as a universal one and compatible with AMD and CommonJS.
- CommonJS, in turn, is the module system created for Node.js server.
- ECMAScript (also referred to as ES) was developed later as a system which both CommonJS and AMD users would be happy with.
More About ECMAScript Modules
As I said, the idea of ECMAScript modules was to make both CommonJS and AMD users happy. So, this system adopted a very simple but effective style rules:
- Each module is a piece of code, and it is executed once loaded.
- This code may include declarations of variables, functions, and so on. These declarations are local to the module.
- If you mark these declarations as exports, other modules can import them.
- “export” is a label that makes variables and functions accessible from outside the current module; “import” is a label that allows the use of functionality from other modules.
- For a module to import a declaration from a different module, the former refers to the latter via module specifiers. These module specifiers can be the following:
- Relative paths. These paths point relatively to the location of the importing module.
- Absolute paths. These paths point directly to the file from which the module should be imported.
- Names. Each name refers to a certain module as configured.
- Each module is a singleton. That is, if a module is imported a few times, there still exists a single instance of it.
- There are no global variables — only module specifiers are global.
This module system is now supported by all major browsers but for Internet Explorer. The convenience and universality of ECMAScript paved its road to popularity and success.
ECMAScript Modules and Node.JS
Once ECMAScript modules were introduced in JavaScript, the lives of all JS developers became much easier. Only Node.js developers were the exception to the rule — Node still had its own module system, Common JS. All these years, Node developers had to find their way around two module systems — Common JS in Node and ECMAScript in any other framework used on the project. To organize code in modules, developers had to use transpilers, such as Babel. Respectively, the number of development hours and the probability of compatibility errors increased.
Things changed when the latest version of Node was released.
Node.js v14 offers full support of ECMAScript modules, and it is enabled by default. However, the interoperability between ECMAScript modules and CommonJS modules is still limited. The Node community urges developers to expect major changes in terms of interoperability soon.
The following files will be treated as ECMAScript modules:
- Files ending in .js if there is a top-level field “type” with a value of “module” in the nearest parent package.json file
- Files ending in .mjs
- Strings passed in as an argument to –eval or –print, or piped to node via STDIN, with the flag –input-type=module.
The following files will be treated as CommonJS modules:
- Files ending in .js if there is a top-level field “type” with a value of “commonjs” in the nearest parent package.json file
- Files ending in .js if there is no top-level field “type” in the nearest parent package.json file
- Files ending in .cjs
- Strings passed in as an argument to –eval or –print, or piped to node via STDIN, with the flag –input-type=commonjs.
- Strings passed in as an argument to –eval or –print, or piped to node via STDIN, without the flag –input-type
All the conditions supported by Node.js except “require” — that is “import”, “default”, and “node” — support both ECMAScript and CommonJS modules. The “require” condition is unique to CommonJS. Similarly, there are no “exports”, ”module.exports”, ”__filename”, ”__dirname”, “NODE_PATH”, “require.extensions”, “require.cache”, or “require.resolve” in ECMAScript.
“Require.resolve” can be implemented via “import.meta.resolve”, which is experimentally supported via the “–experimental-import-meta-resolve” flag.
When using the “import” keyword, unlike in CommonJS, in ECMAScript modules, a file extension must be provided and directory indexes must be fully specified.
As for other conditions — such as “browser” or “react-native”, which may be supported by tools and environments other than Node.js, — there is no precise guidance in Node v14 documentation, but it is expected to be offered later.
So, What’s Next?
The 14th version of Node changed things. Now, ECMAScript is implemented in Node, so the module system gap between Node and other JS frameworks has been bridged. Now, since there is no need for transpilations, the concept of isomorphic JavaScript becomes a lot easier to implement. In turn, this brings such significant benefits as improved user experience, better performance, and simpler indexing of web applications.
As a Node.js development company, we observed this update for quite a while now and waited for the flag “Experimental” to be taken down. Finally, this change is out there — maybe not 100 percent perfectly implemented, and some bugs will definitely persist in a few future version updates. Yet, it is a huge and very promising step ahead.
Does it seem to you that Node.js is the framework you need? Please, find out more about Node.js development services that we offer.