如何正确配置实验性 ECMAScript 模块,以便在 Node.js 中使用导入/导出

Posted

技术标签:

【中文标题】如何正确配置实验性 ECMAScript 模块,以便在 Node.js 中使用导入/导出【英文标题】:How to correctly configure experimental ECMAScript module so import/export can be used in Node.js 【发布时间】:2018-10-06 15:39:43 【问题描述】:

时间在飞逝,现在 Node.js ver.10.0.0 已经向公众发布。当我使用我的 MERN 堆栈时,我经常需要在前端 (React.JS) 的 ES6 import/export 语法和我的 Node/Express 服务器端的 CommonJS module.exports/require 语法之间切换。而且我真的希望写作风格能够很快在 import/export 中统一,而不使用 Babel 并从原生支持中获得它。

一个好消息是自从去年我读到James' post on Medium解决了在 Node.js 中实现 ES6 模块系统的困难,实验性的 ECMAScript 模块现在处于稳定状态 1 一段时间,这意味着它可以启用由--experimental-modules 标志。

但是,当我尝试在 Node 上使用 import/export 语法时,它永远无法正常工作。例如,我试过这个:

import fs from 'fs';
console.log(typeof fs.readFile);

上面的代码会报错:

(function (exports, require, module, __filename, __dirname)  import fs from 'fs';
                                                                     ^^
SyntaxError: Unexpected identifier

我确定我已经启用了调用为 $node --experimental-modules 的实验标志,那么我应该怎么做才能在我的 Node 本地服务器上启动 ES6 import/export 实验模块?我错过了什么?


添加:

我之所以要尝试这个实验性功能,是因为前后编码风格一致。而且因为它现在可以在本地使用,所以我想做好准备。一旦达到第 2 阶段,我就可以快速适应import/export 并减少痛苦。

但很明显,Google (ref) 和 AirBnb(ref) 对于我们是否应该在他们的代码风格指南中使用 import/export 语法有不同的看法。而且基于谷歌,我仍然感到惊讶的是,ES6 导入/导出的语义尚未最终确定,而 ECMA2019 正在进行中。我只是想知道我什么时候可以在我的项目中真正使用import/export,或者真正需要完成什么?


更新:

在Jaromanda X 指出后,如果我将文件名更改为.mjs,那么它可以工作。本来我以为要加载的模块必须以.mjs扩展名命名,但似乎我错了。但是,如果是这种情况,这意味着我需要将我的所有项目文件重命名为 .mjs...,这并不吸引人。只是想知道是否有办法在传统的.js 文件中使用此功能?我应该配置什么?

【问题讨论】:

你的文件扩展名是.mjs 不,你的文件如果你的文件,扩展名是什么 不知道,虽然它是实验性的,但我避免它:p common.js 出了什么问题?为什么该模块系统不能成为官方规范客户端? ES 模块导入/导出在 javascript 中感觉不自然。 @Darkrum Commonjs require 不是声明性的,不支持异步加载 【参考方案1】:

此时ECMAScript Module在node.js v10中还没有敲定,所以不建议在生产环境中使用。由于 import/export 的使用在 ECMAScript 规范中是标准化的,所以无论如何,node 为社区提供这样的支持很重要。

require()ECMAScript 模块 之间的主要区别在于节点将如何处理其缓存。与require() 不同,目前ECMAScript 模块 没有这样的API 来操作模块缓存。另外,不带加载器的普通*.js文件是否会直接支持尚不清楚,敬请期待。

现在的方向是尝试引入一个新的*.mjs文件来明确显示它使用标准的JS模块(符合ES6),但是如果仔细阅读doc你实际上可以看到它也是可能的指定您自己的扩展匹配,包括使用更传统的*.js。但是,它需要更多的配置并使用--loader 标志来加载额外的配置。

支持6种不同的格式,包括一种用C++编写的模块(也可以通过require()加载),非常强大。总之,要使用*.js文件扩展名,在loader中的关键设置是:

const JS_EXTENSIONS = new Set(['.js', '.mjs']);

加载器函数需要检查要加载的文件是否在JS_EXTENSIONS 数据集中。这里,loader 函数的关键是它应该返回一个具有两个属性的对象:urlformat,即:

return 
  url: (...),    // e.g. './x?n=1234'
  format: 'esm', // there are 5 + 1 dynamic formatting
;

建议将loader命名为custom-loader.mjs,并使用$node --experimental-modules --loader ./custom-loader.mjs,因为官方doc有演示。一旦你正确配置了加载器(根据你的需要),那么你应该能够使用import/export,就像你可以在你的节点项目中的前端反应应用程序中使用一样。

【讨论】:

以上是关于如何正确配置实验性 ECMAScript 模块,以便在 Node.js 中使用导入/导出的主要内容,如果未能解决你的问题,请参考以下文章

翻译 | 浏览器中的ECMAScript模块

加载配置时出错 - 您似乎正在使用本机 ECMAScript 模块配置文件 (Jest)

第05章 管理ElasticSearch

如何使用“ModuleConcatenation 救助:模块不是 ECMAScript 模块”救助消息修复模块?

如何使用 ECMAScript 6 模块导入 PlotlyJS

宝,如何动态导入ECMAScript模块?