Translated from:
Using ES modules natively in Node.js, the original author is
Dr. Axel Rauschmayer, the circle called “German Ruan Yifeng”.

Node.js has supported ES modules natively since 8.5.0, but still requires command line arguments. This is thanks to Bradley Farias’ contribution to this new feature.

This article describes this feature in detail.

Take a chestnut

File structure:

esm-demo/
    lib.mjs
    main.mjs
Copy the code

Lib. MJS:

exportfunctionadd(x, y) {
    return x + y;
}
Copy the code

The main MJS:


import {add} from'./lib.mjs';

console.log('Result: '+add(2, 3));
Copy the code

Run example:

$ node --experimental-modules main.mjs
Result: 5
Copy the code

Pay attention!

Module name of ES:

  • All module names are urls – this introduces something new to Node.js;
  • Files: It is best to use opposite bands.mjsSuffix path to reference ES module, which ensures browser compatibility. If no suffix is included, the module search is the same as CJS. If we find both.mjs.jsFile, then use.mjsFile;
    • Such as:../util/tools.mjs
  • Library modules: Use the module name directly, omitting the extension is best. This is best compatible with the way library modules are distributed at this stage;
    • Such as:lodash
  • How to makenode_modulesThere is still work to be done to see how the bundler module works in the browser (without bundler). One alternative is to introduce a requireJs-class configuration that converts the bare path to the real path. Currently, bare-path modules are not available in browsers;

Features of ES module:

  • Unable to dynamically import modules; But the dynamic operator import() will soon be introduced;
  • like__dirname__filenameAnd such meta-variables will no longer be provided, there is a new proposal introduced that will give ES modules a similar approach – Domenic Denicola proposedimport.meta
console.log(import.meta.url);
Copy the code

Interoperability with CJS modules

  • The ES module can import CJS modules, but the imported module contains only a default export — that is, module.exports value. Plans have been made to have the CJS module print named export (by adding a compile instruction at the beginning of the file), but this may take some time to implement. If you want to help, look here.

      import fs1 from'fs';
      console.log(Object.keys(fs1).length); // 86
    
      import * as fs2 from'fs';
      console.log(Object.keys(fs2)); // ['default']
    Copy the code
  • Require () cannot be called in an ES module, mainly because:

    • Path resolution is quite different in the two specifications: ESM does not support itNODE_PATHrequire.extensions; Its module identifier is always a URL, which makes a small difference;
    • For maximum compatibility with browsers, ES modules are always loaded asynchronously. This asynchronous loading approach works with CJSrequire()Synchronous loading doesn’t work well together;
    • The synchronization module is also disabled to use top-level in ES modulesawaitClosed the door (a feature currently under consideration);
  • CJS cannot require() ES modules. The reason is similar to that mentioned in the previous article, synchronous loading of asynchronous modules various problems ah. However, it might be possible to load the ES module with import().

Use the ES module on older versions of Node.js

Well, if you want to use ES modules on older Node.js, check out John-David Dalton’s @STD/ESM.

Tip: As long as you don’t use the Unlockables feature, you can guarantee full compatibility with native ES Modules.

FAQ

When is it possible to use ES modules without command configuration?

The current plan is to support ES modules directly in the Node.js 10 LTS version;

.mjsDoes it work in a browser?

Yes, just provide the correct Media Type (text/javascript or Application /javascript). The standardization of MJS and the upgrade of peripheral tools are in progress.

File extension.mjsIs it required for the ES module?

Yes, that’s true for Node.js. Browsers don’t care about file extensions, just Media types.

Why is Node.js needed.mjs?

Node.js could have checked whether a file was a CJS module or an ES module. Several other options were discussed before choosing the option of adding extensions. You can read another post on this blog. Each scheme has its advantages and disadvantages. In my opinion,.mjs is the right choice.