Node v12 中的新 ECMAScript 模块介绍

Introduction

如果你熟悉像React和Angular这样的流行的JavaScript前端框架,那么ECMAScript的概念对你来说不会完全新的。ES模块有我们经常在前端框架中看到的导入导出语法。 **Node使用CommonJS,该框架依赖于require()导入。

新的模块

此前,以前的一個 Node 發行版為 ECMAScript 模組提供實驗性支援)。這項支援在「--實驗式模組」旗帜背後,仍然存在,但自上次發行以來發生了很多事情,我們對接下來的事情感到高興。

突出的反馈是,Node.js需要为您提供一种在.js文件中使用导入和导出语法的方法。

1、在package.json 中设置类型:模块

1// package.json
2    {
3      "type": "module"
4    }

这告诉 Node.js 将您的项目中的所有.js 文件视为 ES 模块. 如果您仍然有不希望被视为模块的 CommonJS 文件,您可以使用.cjs 文件扩展命名它们,这将告诉 Node.js 明确将它们解析为 CommonJS。

如果最近的 parent package.json 文件缺少一个类型字段,或包含类型:commonjs无扩展和.js 文件被视为 CommonJS。如果达到卷根并且没有找到 package.json,Node.js 会转移到默认值,则没有类型 field.import 的 package.json 将被视为 ES 模块,如果最近的 parent package.json 包含类型:模块

你可以认为这种类型和扩展范围是CSS优先顺序的运作方式,它从孩子到父母的树木。

  1. 使用 `--input-type 旗
1node --experimental-modules --input-type=module --eval \
2  "import { sep } from 'path'; console.log(sep);"
3
4echo "import { sep } from 'path'; console.log(sep);" | \
5  node --experimental-modules --input-type=module

使用导入和导出语法的第二种方法是使用 --input-type=module 来运行字符串输入(通过 --eval, --print,或 STDIN`)作为 ES 模块。

更多期待的 WIP 功能

鉴于Node.js 模块团队仍在研究这些功能,我们无法准确地将它们报告为现有功能,为什么?它们仍在进行开发,所以它们都可能仍然会发生变化,然而,我们对它们是什么以及它们可能如何行为有一个想法。

模块加载器

虽然--loaderAPI的第一个实现已经发送,但它仍在进行工作,因此它仍然可能在下一版中发生变化。

包路地图

该功能尚未发布,它将重新定义我们如何进行模块导入,并在某些情况下允许更少的口语导入。

自动入口点模块检测

此功能将使Node能够识别我们在我们的项目中存在的模块类型. 发货后,Node将能够知道特定模块是否是ES模块或CommonJS模块。

在Node v12中有许多其他新功能,请在Medium上的Modules Team(https://medium.com/@nodejs/announcing-a-new-experimental-modules-1be8d2d6c2ff)的官方博客文章中深入了解一下,但与此同时,让我们仔细看看我们在Node中所拥有的模块类型。

节点中的不同类型的模块

这在这一点上可能看起来很明显,但我从经验中了解到,大多数人很难理解我们在Node中所拥有的不同类型的模块. 鉴于直到最近,我们在Node中所需要的只是CommonJS语法,很容易理解一些人发现它令人困惑。

在 Node 中有两种模块类型。

  1. CommonJS 模块类型
  2. ES 模块类型

CommonJS 模块

CommonJS 模块是与 Node 附带的默认模块. 在 ES 模块启动之前,每个 Node 应用程序都与使用require()module.exports语法将模块拉进并导出的 CommonJS 模块构造一起工作。

1//src/main.js
2var products = require('src/products'); // import module

在这里,我们刚刚从我们的应用程序的src目录中的另一个文件中导入了一个产品模块到我们的main.js文件中。我们可以继续使用当前文件中的模块,如我们所愿。

1//src/products.js
2exports = function(){
3    return response.get('all-products);
4}

Node.js 应用程序

Node.js 的实现与我们刚刚从 CommonJS 看到的并不太不同. 区别在于模块是从主机文件中导出的方式. 虽然 CommonJS 导出具有导出变量的模块,但 Node 模块使用module.exports对象。

1//src/products
2function products(){
3    return response.get('all-products);
4}
5modules.exports = products;

就像CommonJS实现一样,这是一个同步的过程,因为文件在文件内部出现的顺序下加载一个接一个。

模块

ES 模块可以被认为是 CommonJS 模块系统的改进,它提供了导入和导出模块的可能性,仅通过使用导入导出关键字来替代 CommonJS 中的要求

考虑到我们在上面的例子中用 CommonJS 看到的产品示例,我们可以用 ES 模块这样重写文件:

1//src/main.js
2import products from 'src/products'

正如我们之前所解释的那样,导入语句用于将模块带入名称空间. 它几乎像 CommonJS 中的要求替代方案一样运行,但它不是动态的,因此,您不能在文件中任何地方使用它。

1//src/products.js
2export function products() {
3    return response.get('all-products);
4}

这里的导出声明使您能够从另一个文件访问这个函数。简单地说,它使该函数广泛可用. 因此,静态分析器将首先构建依赖树,同时组合文件,然后最终运行代码。

ESM在过去的节点

Node 中的 ES 模块的概念并不完全新鲜,它自 2017 年以来一直可用,当时 Node.js 8.9.0 向 ECMAScript 模块提供实验性支持,以它们的导入和导出声明为名。

然而,到目前为止,这个功能一直处于实验状态。理由?让Node.js社区有时间使用它,并提供可操作的反馈。自那时起,发生了很多事情。主要浏览器(现在支持)(https://caniuse.com/#feat=es6-module) ECMAScript模块(ES模块)通过<script type="module">。与ES模块来源的npm包现在可以通过comments powered by Disqus