ecmascript v3
介绍 (Introduction)
If you’re familiar with popular JavaScript frontend frameworks like React and Angular, 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. We can now use import and export in Node in addition to require()
. That’s not all that comes with the new Node v12 release, let’s talk about all the new cool features we can expect.
如果您熟悉React和Angular等流行JavaScript前端框架,那么ECMAScript的概念对您来说并不是一个全新的概念。 ES模块具有我们在前端框架中经常看到的import
和export
语法。 ** Node使用CommonJS依赖于import的require()
。 现在,除了require()
之外,我们还可以在Node中使用导入和导出。 不仅仅是新的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 are provided for you to this:
出色的反馈是Node.js需要提供一种在.js
文件中使用导入和导出语法的方法。 在新的--experimental-modules
,为此提供了两种方法:
Set
“type” : “module”
inpackage.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。
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文件缺少
type
字段或包含"type": "commonjs"
,"type": "commonjs"
扩展名和.js文件视为CommonJS。 如果到达卷根目录且未找到package.json,则Node.js"type" field.import
默认设置,如果没有最近的父级,则没有"type" field.import
的package.json。.js和无扩展文件的"type" field.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优先顺序的工作方式,它将树从子级一直降级到父级。
Use the
--input-type flag
“`bash node –experimental-modules –input-type=module –eval \ "import { sep } from ‘path’; console.log(sep);”使用
--input-type flag
“`bash节点–experimental-modules –input-type = module –eval \“从'path'导入{sep}; console.log(sep);”
echo “import { sep } from 'path’; console.log(sep);” | \ node –experimental-modules –input-type=module
从“路径”中回显“ import {sep}”; console.log(sep);” | \节点–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.
## 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.
## 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.
## 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.
There are so many other new features in Node v12, feel free to dig deeper in the official blog post by [the Modules Team](https://medium.com/@nodejs/announcing-a-new-experimental-modules-1be8d2d6c2ff) on Medium. But in the meantime, let’s take a closer look at the types of modules we have in Node.
## Different Types of Modules in Node
This might look 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.
There are two module types in Node.
1. The CommonJS Module type
1. The ES Module type
###CommonJS Module
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:
```javascript
//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实现 (Node.js implementation)
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模块 (ES Modules)
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 its 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模块)。 现在可以通过<script type="module">
在浏览器中使用带有ES模块源的npm软件包。 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
实现,并--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. nvm lets you install multiple versions of node on one machine and switch between them when you need to.
在等待对ESM的长期支持的同时,我们可以使用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 two 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中返回相同的对象。 考虑下面的示例:
import productsConfif from './package.json';
For this to actually work, we’ll need to update
为使此方法切实可行,我们需要更新
node --experimental-modules index.js
to
至
node --experimental-modules --entry-type=module --experimental-json-modules index.js
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 article 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://www.digitalocean.com/community/tutorials/new-ecmascript-modules-in-node-v12
ecmascript v3