# 为什么node不支持ESM(ECMAScript module)? - https://github.com/nodejs/help/issues/53 - https://stackoverflow.com/questions/36901147/es2015-import-not-working-in-node-v6-0-0-with-with-harmony-modules-option - https://github.com/cisen/blog/issues/620 - [ES6模块和require的差异](https://hackernoon.com/node-js-tc-39-and-modules-a1118aecf95e) - - Node.js和TC-39对“模块”是什么,如何定义以及如何将它们加载到内存和使用中有着截然不同的想法。 - - node的require实现的原理是: - - - 1. 执行的时候,通过require函数确定文件的绝对路径 - - - 2. 通过绝对路径匹配文件,然后加载整个文件到内存中,然后parser - - - 3. 使用一个函数包裹模块代码字符串,比如: ```js // 包裹前 const m = 1; module.exports.m = m; // 包裹后 function(exports,require,module,__ filename,__ dirname){ const m = 1; module.exports.m = m; } ``` - - - 4. 使用VM虚拟机进行执行模块文件 - - **所以,在执行包裹函数前,无法预知该模块导出了什么,依赖树是怎样的。这也是跟ES6模块的根本区别所在。而ESM在执行前,已经通过parse建立module map,链接map到各个模块的内存中,执行除了导出模块内部代码外的所有父级执行域代码。就是ESM导入模块前,就已经执行了所有依赖树的全局作用域代码,获得了各个作用域的变量池** - 首先node的require够用 - 可以通过`node --v8-options | grep harmony `获取node最新特性 - **网络加载问题,这个才是大问题**,https://github.com/WICG/import-maps - node 目前使用`.mjs`后缀来兼容ESM - node.js准备在12版内支持,进程:https://github.com/nodejs/node/pull/26745 # ECM的实现 - https://github.com/cisen/blog/issues/535 # node 如何调用ECM - 注意文件名后缀是`.mjs`和使用`--experimental-modules`变量 - https://nodejs.org/dist/latest-v12.x/docs/api/esm.html - **只要有import就会调用那个文件的全局作用域,不管该导入模块有没有执行** - **多次import同一个文件,全局作用域也只运行一次,实现通过module map实现** - **由于import/export指向同一个内存地址,所以可以`import aa from 'aa.mjs`直接修改aa的值,然后别的模块引入aa的值的时候也是最新的值** ```js // a.mjs function aa() { console.log('aa'); } export default aa; ``` ```js // b.mjs import aa from './test.mjs'; aa(); ``` ```js console.log('pre cc') function aa() { console.log('cc'); } export default aa; ``` **这里的输出比较有趣,可以看到是import的时候直接运行模块外面的全局代码,然后运行完所有import的代码才执行调用代码 ``` node --experimental-modules bb.mjs # pre aa # pre cc # aa # cc ```
为什么node不支持ESM(ECMAScript module)?
node --v8-options | grep harmony获取node最新特性.mjs后缀来兼容ESMECM的实现
node 如何调用ECM
.mjs和使用--experimental-modules变量import aa from 'aa.mjs直接修改aa的值,然后别的模块引入aa的值的时候也是最新的值**这里的输出比较有趣,可以看到是import的时候直接运行模块外面的全局代码,然后运行完所有import的代码才执行调用代码