node --experimental-modules & node.js ES Modules_export node --experimental-modules node.js ES Modules ESM CJS ES Modules .mjs



node --experimental-modules & node.js ES Modules

how to run esm modules in node.js cli

$ node -v
# v12.18.0

$ uname -a
# Darwin xgqfrms-mbp.local 19.5.0 Darwin Kernel Version 19.5.0: Tue May 26 20:41:44 PDT 2020; root:xnu-6153.121.2~2/RELEASE_X86_64 x86_64


​.mjs​​ & ​​"type": "module",​

.mjs

// package.json
{
"type": "module"
}



node --experimental-modules & node.js ES Modules_exports_02

--experimental-modules

# node --experimental-modules

# ✅ must include `.mjs` file extension name
$ node --experimental-modules esm-node.mjs

$ node --experimental-modules --input-type=module ./esm-node.mjs


​.js​​ bug ❌

node --experimental-modules & node.js ES Modules_export

node --experimental-modules & node.js ES Modules_exports_04

// .js
import { a } from "./esm-modules";
import { b } from "./esm-modules";

// import { c } from "./esm-modules";
// import { d } from "./esm-modules";

import esm from "./esm-modules.mjs";

const log = console.log;

log(`a =`, a)
log(`b =`, b)
log(`c =`, esm.c)
log(`d =`, esm.d)


​.mjs​​ solution ✅

you must import es module with the ​​.mjs​​ file extension name

// defualt `.js` ❌
/*
import { a } from "./esm-modules";
import { b } from "./esm-modules";
import { c } from "./esm-modules";
import { d } from "./esm-modules";
*/


// .mjs ✅
import { a } from "./esm-modules.mjs";
import { b } from "./esm-modules.mjs";
// import { c } from "./esm-modules.mjs";
// import { d } from "./esm-modules.mjs";

import esm from "./esm-modules.mjs";


node --experimental-modules & node.js ES Modules_exports_05

module.exports & exports

CJS Modules


// CJS Modules

/*
exports.a = 1;
exports.b = 2;
exports.c = 3;
exports.d = 4;

// exports = { a: 1, b: 2, c: 3, d: 4 }

*/


exports.a = 1;
exports.b = 2;
module.exports = { c: 3 };
module.exports.d = 4;

// module.exports = { c: 3, d: 4 }


✅ 结论

  1. exports just shorthand of module.exports
  2. if exist both exports & module.exports, module.exports will be overwritten exports ⚠️
  3. best practice, just using module.exports as possible as you can

exports.a = 1;
exports.b = 2;
module.exports = { c: 3 };
module.exports.d = 4;

// module.exports = { c: 3, d: 4 }

console.log(module);



node --experimental-modules & node.js ES Modules_CJS_06


exports.a = 1;
exports.b = 2;
module.exports = { c: 3 };
module.exports.d = 4;

// module.exports = { c: 3, d: 4 }

module.exports.hello = true; // Exported from require of module
exports = { hello: false }; // Not exported, only available in the module

console.log(`hello =`, exports);
console.log(module);


node --experimental-modules & node.js ES Modules_CJS_07

export default & export

ESM Modules


/* eslint-disable no-unused-vars */

// eslint-disable-next-line no-unused-vars
const a = 1;
const b = 1;
const c = 1;
const d = 1;

const esm = {
// a,
// b,
c,
d,
};

export {
a,
b,
}

export default esm;