ecmascript v3
If you’re familiar with popular JavaScript frontend frameworks like React, Angular, etc, then the concept of ECMAScript won’t be entirely new to you. ES Modules have the import
and export
syntax we see often in frontend frameworks. Node uses CommonJS which relies on require()** for imports.**
如果您熟悉流行JavaScript前端框架(如React,Angular等),那么ECMAScript的概念对您来说并不是一个全新的概念。 ES模块具有我们在前端框架中经常看到的import
和export
语法。 Node使用CommonJS,它依赖于require ()**进行导入。**
We can now use import and export in Node in addition to require().
现在,除了require()之外,我们还可以在Node中使用导入和导出。
That’s not all that comes with the new Node v12 release, let’s talk about all the new cool features we can expect.
不仅仅是新的Node v12版本附带的内容,让我们谈谈我们可以期待的所有新功能。
Node v12中的新功能 ( New features in Node v12 )
新的ES模块 ( New ES Modules )
Before now, a previous Node release shipped with experimental support for ECMAScript modules. This support was behind the --experimental-modules
**flag and still is, but a lot has happened since the last release and we are happy for what is coming next. We know for a fact that some of the concerns and feedbacks raised from the last release has been acted on and is coming to life in the next release.
在此之前,先前的Node版本附带了对ECMAScript模块的实验性支持。 该支持位于--experimental-modules
**标志后面,并且仍然存在,但是自从上一发行版以来发生了很多事情,我们对接下来的发展感到高兴。 我们知道,上一个版本提出的一些关注和反馈已付诸实践,并在下一个版本中付诸实践。
The outstanding feedback being that Node.js needs to provide a way to use import and export syntax in *.js*
files. In the new --experimental-modules
, two ways will be provided for you to be able to do this:
杰出的反馈是Node.js需要提供一种在*.js*
文件中使用导入和导出语法的方法。 在新的--experimental-modules
,将提供两种方法来执行此操作:
- Set “type” : “module” in
package.json
在package.json
设置“ type”:“ module”
// package.json{
"type": "module"
}
This tells Node.js to treat all .js
files in your project as ES Modules. If you still have CommonJS files that you would not like to treat as modules, you can rename them with the .cjs
file extension, which will tell Node.js to parse them as CommonJS explicitly. Alternatively, you can put all your CommonJS files in a subfolder containing a package.json
file with "type":"commonjs"
, under which all .js
files are treated as CommonJS.
这告诉Node.js将项目中的所有.js
文件都视为ES模块。 如果仍然有不希望作为模块的CommonJS文件,则可以使用.cjs
文件扩展名重命名它们,这将告诉Node.js明确地将它们解析为CommonJS。 另外,您也可以将所有CommonJS文件放在一个子文件夹中,该子文件夹包含带有"type":"commonjs"
的package.json
文件,在该子文件夹下所有.js
文件都被视为CommonJS。
Note, If the nearest parent package.json file lacks a "type" field, or contains "type": "commonjs", extensionless and .js files are treated as CommonJS. If the volume root is reached and no package.json is found, Node.js defers to the default, a package.json with no "type" field.import statements of .js and extensionless files are treated as ES modules if the nearest parent package.json contains "type": "module".
注意,如果最近的父package.json文件缺少“类型”字段,或包含“类型”:“ commonjs”,则将无扩展名和.js文件视为CommonJS。 如果到达卷根目录且未找到package.json,则Node.js会遵循默认设置,如果没有最近的父级,则没有“类型”字段的package.json。.js和无扩展文件的import语句将被视为ES模块。 package.json包含“ type”:“ module”。
You can think of this type and extension scoping as the way CSS order of precedence works, it cascades down the tree from the child all the way up to the parent.
您可以将这种类型和扩展范围定义为CSS优先顺序的工作方式,它将树从子级一直降级到父级。
2.** Use the** --input-type flag
2 。**使用**- 输入 类型标志
node --experimental-modules --input-type=module --eval \
"import { sep } from 'path'; console.log(sep);"
echo "import { sep } from 'path'; console.log(sep);" | \
node --experimental-modules --input-type=module
The second way of using the import and export syntax is to use --input-type=module
to run string input (via --eval, --print or STDIN) as an ES module. The --input-type
flag can be either --input-type=module
or --input-type=commonjs
. In our case, it’ll be the earlier since we are setting it to modules, not CommonJS.
使用导入和导出语法的第二种方法是使用--input-type=module
将字符串输入(通过--eval,--print或STDIN)作为ES模块运行。 --input-type
标志可以是--input-type=module
或--input-type=commonjs
。 在我们的情况下,它将是更早的,因为我们将其设置为模块而不是CommonJS。
更多预期的WIP功能 ( More expected WIP features )
Given that the Node.js Modules team are still working on these features, we can’t exactly report them as existing features. Why? they are still being worked on so they are all probably still going to change, however, we have an idea of what they are and how they are likely to behave.
鉴于Node.js模块团队仍在研究这些功能,因此我们无法将其准确报告为现有功能。 为什么? 它们仍在研究中,因此它们可能都将继续发生变化,但是,我们对它们是什么以及它们的行为方式有所了解。
模块装载机 ( Module Loaders )
The Very WIP feature. Though the first implementation of the --loader
API has shipped, it's still being worked on hence, it is still subject to changes **in the next release.
非常在制品功能。 尽管--loader
API的第一个实现已经发布,但仍在开发中,因此在下一发行版中仍可能会发生变化。
包路径图 ( Package path maps )
This feature has not shipped yet. It would redefine how we make module imports and allow for less verbose imports in certain situations.
此功能尚未发货。 它将重新定义我们如何进行模块导入,并在某些情况下允许较少的详细导入。
自动进入点模块类型检测 ( Automatic entry point module type detection )
This feature will make it possible for Node to identify the type of module we have present in our projects. When shipped, it will be possible for Node to know if a particular module is an ES Module or a CommonJS Module.
此功能将使Node可以识别项目中存在的模块类型。 出厂时,Node可以知道特定模块是ES模块还是CommonJS模块。
There are so many other awesome features in Node v12, feel free to dig deeper and get a piece of the awesomeness in the official blog post by the Modules Team on Medium. But in the meantime, let’s take a closer look at the types of modules we have in Node.
Node v12中还有许多其他令人敬畏的功能,可以随时深入研究,并在Medium上的Modules Team的官方博客文章中了解这些令人敬畏的内容。 但是与此同时,让我们仔细看看Node中的模块类型。
节点中不同类型的模块 ( Different Types of Modules in Node )
This might look very obvious at this point but i have come to understand with experience that most people have troubles understanding the different types of modules we have in Node. Given that until recently, all we needed in Node is the CommonJS syntax, it’s understandable that a few people find it confusing.
在这一点上,这看起来似乎很明显,但是我已经从经验中了解到,大多数人都难以理解Node中拥有的不同类型的模块。 鉴于直到最近,我们在Node中所需要的只是CommonJS语法,可以理解有些人感到困惑。
There are basically two module types in Node.
Node中基本上有两种模块类型。
- The CommonJS Module type and CommonJS模块类型和
- The ES Module type ES模块类型
CommonJS Module
CommonJS模块
The CommonJS Module is the default module that comes with Node. Before the inception of the ES Modules, every Node application works with the CommonJS module construct that uses the require()
and module.exports
syntax to pull in modules and export them. Consider this example:
CommonJS模块是Node随附的默认模块。 在ES模块开始之前,每个Node应用程序都与CommonJS模块构造一起使用,该构造使用require()
和module.exports
语法引入并导出模块。 考虑以下示例:
//src/main.js
var products = require('src/products'); // import module
Here, we just imported a products
module into our main.js
file from a different file in our app’s src
directory. We can go ahead and use the module in the current file as we please. How is this possible? Because the products
function is set to the exports object in the src/products
file according to CommonJS specification.
在这里,我们只是将products
模块从应用程序src
目录中的其他文件导入到main.js
文件中。 我们可以继续并根据需要使用当前文件中的模块。 这怎么可能? 因为products
功能根据CommonJS规范设置为src/products
文件中的导出对象。
//src/products.js
exports = function(){
return response.get('all-products);
}
Node.js implementation
节点 。 js实现
The Node.js implementation is not so different from what we’ve just seen above from CommonJS. The difference is in the way the modules are exported from their host files. While CommonJS exports modules with the exports
variable, Node modules uses module.exports
object.
Node.js的实现与上面从CommonJS看到的没有太大不同。 不同之处在于模块从其主机文件导出的方式。 当CommonJS使用exports
变量导出模块时,Node模块使用module.exports
对象。
//src/products
function products(){
return response.get('all-products);
}
modules.exports = products;
Just like the CommonJS implementation, this is equally a synchronous process as the files are loaded one after the other in the order they appear inside the file.
就像CommonJS实现一样,这同样是一个同步过程,因为文件按照它们在文件中出现的顺序一个接一个地加载。
ES Modules
ES模块
ES Modules can be considered an improvement on the CommonJS module system. It offers possibilities for importing and exporting modules just by using the import
and export
keywords as a replacement for require
in CommonJS. Unlike CommonJS, the ES Modules are compatible with both synchronous and asynchronous modes of operation.
ES模块可以被认为是CommonJS模块系统的改进。 它仅通过使用import
和export
关键字替代CommonJS中的require
提供导入和导出模块的可能性。 与CommonJS不同,ES模块与同步和异步操作模式兼容。
Considering the products example we saw with CommonJS on the previous examples above, we can redo the file with ES Modules like so:
考虑到我们在上面的先前示例中使用CommonJS看到的产品示例,我们可以使用ES模块重做该文件,如下所示:
//src/main.js
import products from 'src/products'
As we explained before, the import
statement is used to bring modules into the namespace. It operates almost exactly as the require alternative in CommonJS but it is not dynamic, hence, you cannot use it anywhere in the file. Again, we were able to import this file for use here because it has probably been exported from it’s host file.
如前所述, import
语句用于将模块引入命名空间。 它几乎与CommonJS中的require替代完全一样运行,但是它不是动态的,因此,您不能在文件的任何位置使用它。 同样,我们能够导入此文件以在此处使用,因为它可能已从其主机文件中导出。
//src/products.js
export function products() {
return response.get('all-products);
}
The export
statement here makes it possible for you to access this function from another file. Simply put, it makes the function widely accessible. As a result of this, static analyzers will first build the tree of dependencies while bundling the file before eventually running code. This is in my opinion a major advantage of using ES Modules.
此处的export
语句使您可以从另一个文件访问此功能。 简而言之,它使该功能可广泛访问。 结果,静态分析器将首先构建依赖关系树,然后在最终运行代码之前捆绑文件。 我认为这是使用ES模块的主要优势。
过去在Node中的ESM ( ESM in Node in the past )
The concept of ES Modules in Node is not exactly new, it’s been available since 2017 when Node.js 8.9.0 shipped experimental support for ECMAScript modules, known for their import and export statements behind the --experimental-modules
flag.
Node中的ES模块的概念并不是一个全新的概念,自2017年Node.js 8.9.0交付了对ECMAScript模块的实验性支持以来就可用了, ECMAScript模块以--experimental-modules
标志后面的导入和导出语句而--experimental-modules
。
However, up until this moment, this feature has remained in the experimental state. Reason? to allow the Node.js community the time to use it and provide actionable feedback on that design. Since then, a lot has happened. Major browsers now support ECMAScript modules (ES modules) via *<script type=*``"``*module*``"``*>*
. Npm packages with ES module sources are now available for use in browsers via *<script type=*``"``*module*``"``*>*
. Support for import maps, which bring to browsers Node.js-style package names in import
statements, is coming to Chrome. And a lot more other things.
但是,直到这一刻,此功能仍处于实验状态。 原因? 以便Node.js社区有时间使用它并提供有关该设计的可行反馈。 从那以后,发生了很多事情。 现在,主要的浏览器通过*<script type=*``"``*module*``"``*>*
支持 ECMAScript模块(ES模块)。 带有ES模块源的Npm软件包现在可以通过*<script type=*``"``*module*``"``*>*
在浏览器中使用。 Chrome即将支持导入地图 ,该导入地图将import
语句中的Node.js样式的软件包名称引入浏览器 。 还有更多其他事情。
Having waited for a long time, received feedback on the experimental ESM design and owing to the fact that there are other runtimes and environments where ES modules are in use, there’s no better time for Node.js to support this ESM JavaScript standard than now. And this is why the Modules Team has announced a new implementation for supporting ES modules. According to them, it will ship as part of Node.js 12 and will replace the old *--experimental-modules*
implementation, behind the same flag.
等待了很长时间,收到了关于实验性ESM设计的反馈,并且由于存在其他运行时和环境都在使用ES模块的事实,现在没有比现在更好的时间让Node.js支持此ESM JavaScript标准了。 这就是模块团队宣布支持ES模块的新实现的原因。 根据他们的说法,它将作为Node.js 12的一部分发布,并将替换旧的*--experimental-modules*
实现,并保留在同一标志的后面。
使用nvm入门v12 ( Get started with v12 using nvm )
While we wait for a long term support for ESM, we can start getting familiar with its operations and features using nvm. What is nvm? nvm lets you install multiple versions of node on one machine and switch between them when you need to.
在等待对ESM的长期支持的同时,我们可以使用nvm开始熟悉其操作和功能。 什么是nvm? nvm使您可以在一台计算机上安装多个版本的节点,并在需要时在它们之间切换。
What this means is that, even though you’re currently running Node v6 or v10 whatever version, you can switch up to the latest version or an older version and try out things while still keeping your current version and files intact.
这意味着,即使您当前正在运行Node v6或v10的任何版本,也可以切换到最新版本或旧版本并尝试进行操作,同时仍保持当前版本和文件不变。
I would love to cover how you can go about installing nvm, and using it to manage your Node versions to try out different features that don’t yet exist in your current version but Michael Wanyoike has already done a great job at it on this post on Sitepoint. If you will be interested in learning how nvm works on different OSS platforms, give the post a visit.
我很乐意支付你可以如何去安装NVM ,并用它来管理你的节点的版本试试那还不存在在当前版本不同的特点,但迈克尔Wanyoike已经在这样的事做了很多工作职位在Sitepoint上 。 如果您有兴趣了解nvm在不同OSS平台上的工作方式,请访问此文章。
使用—experimental-modules标志在LTS之前支持导入 ( Use —experimental-modules flag to support imports until LTS )
Like we mentioned earlier on in this post, ES Modules has been around for a while and there are basically two intuitive ways we can go about using them until LTS.
就像我们在本文前面提到的那样,ES模块已经存在了一段时间,并且基本上有两种直观的方法可以使用它们直到LTS。
node index.js --experimental-modules
node index.js --experimental-modules
node --experimental-modules index.js
node --experimental-modules index.js
Unfortunately the first way i.e using the node index.js --experimental-modules
does not work, hence, to support ESM imports in your Node applications, you will have to use the second option above.
不幸的是,第一种方法(即使用node index.js --experimental-modules
不起作用,因此,要在您的Node应用程序中支持ESM导入,您将不得不使用上面的第二个选项。
动态导入无处可去 ( Dynamic imports is going nowhere )
It is worthy to note that dynamic imports are not under any threat from the incoming ES Modules implementation. Prior to this ESM era, dynamic imports provided us with the ability to dynamically import and use modules from different locations in our application.
值得注意的是,动态导入不会受到传入的ES模块实现的任何威胁。 在这个ESM时代之前,动态导入为我们提供了从应用程序中不同位置动态导入和使用模块的能力。
Given that dynamic imports returns a promise for the module namespace object of the requested module, it's possible to use async/await
and the .then()
-based callback style to handle all module behaviours which makes it possible to load modules asynchronously. This is why we all love it and it’s just a good news to know that we won’t lose it to the new implementations.
鉴于动态导入返回了所请求模块的模块命名空间对象的承诺,因此可以使用async/await
和基于.then()
的回调样式来处理所有模块行为,从而可以异步加载模块。 这就是我们大家都喜欢它的原因,并且知道我们不会在新的实现中失去它只是一个好消息。
导入JSON文件呢? ( What about importing JSON files? )
For now, importing JSON modules are not supported out of the box yet in the module
mode. It is however, supported in the commonjs
mode and are loader with the CJS loader. That said, efforts are currently being made to ensure that JSON imports are supported in the module
mode. For instance, at the moment, WHATWG JSON modules are currently being standardized, and are experimentally supported by including the additional flag --experimental-json-modules
when running Node.js.
目前,在module
模式下尚不支持开箱即用地导入JSON模块。 但是,它在commonjs
模式下受支持,并且与CJS加载程序一起作为加载程序。 也就是说,当前正在努力确保在module
模式下支持JSON导入。 例如,目前, WHATWG JSON模块目前正在标准化,并且在运行Node.js时通过包括附加标志--experimental-json-modules
进行实验性支持。
Even though JSON imports are supported out of the box in commonjs
mode, when the --experimental-json-modules
flag is included, both the commonjs
and module
mode will use the new experimental JSON loader.
即使在commonjs
模式下开箱即commonjs
支持JSON导入,当包含--experimental-json-modules
标志时, commonjs
和module
模式都将使用新的实验性JSON加载器。
There’s a bit of a drawback though, the imported JSON only exposes a default
, so right now there is no support for named exports. Since the experimental JSON loader takes precedence over the commonjs
mode too, a separate cache entry is created in the CommonJS cache, to avoid duplication. The same object will be returned in CommonJS if the JSON module has already been imported from the same path. Consider the example below:
虽然有一个缺点,但是导入的JSON仅公开了default
,因此目前不支持命名导出。 由于实验性JSON加载程序也优先于commonjs
模式,因此在CommonJS缓存中会创建一个单独的缓存条目,以避免重复。 如果已经从同一路径导入JSON模块,则将在CommonJS中返回相同的对象。 考虑下面的示例:
For this to actually work, we’ll need to update
为使此方法切实可行,我们需要更新
to
至
The earlier will fail because of the unavailability of the --experimental-json-modules
.
由于--experimental-json-modules
的不可用,较早的版本将失败。
最后的想法 ( Final thoughts )
There’s been so much talk around the new EcmaScript Modules coming to Node.js v12. In this post we took a closer look at it to understand what it offers as compared to the usual CommonJS alternative.
关于Node.js v12中新的EcmaScript模块的讨论很多。 在这篇文章中,我们仔细研究了它,以了解与普通CommonJS替代品相比它提供了什么。
翻译自: https://scotch.io/tutorials/new-ecmascript-modules-in-node-v12
ecmascript v3