Node.js 宣布一个新的 --experimental-modules【译】

原文:Announcing a new --experimental-modulesjavascript

译文地址html

在2017年,Node.js 8.9.0发布了对ECMAScript模块的实验性支持。这种ECMAScript模块的支持是须要在后面加上--experimental-modules标识来运行。java

如今,主流浏览器都能经过<script type=”module”>标签支持ECMAScript 模块 (ES modules) 。各类项目npm包都使用了ES模块编写,而且能够经过<script type= " module " >在浏览器中直接使用。支持导入映射(import maps)即将登录Chrome。import map将让浏览器支持node.js风格的包名导入。node

这些采用ES模块方面的进展大大加快了Node.js对ES模块的支持速度。既然已经有其余运行时和环境在使用ES模块,那么Node.js支持这个JavaScript标准就更重要了。git

Nodejs最初将ES模块做为一个保留实验特性的缘由是为了提供时间让社区去讨论和反馈这种设计。Modules Team创建出来就是为了对这些反馈提供支持,最终致使了一个ES模块的新实现。咱们很高兴地宣布它将做为Node.js 12版本的一部分发布。它将取代旧的实验模块实现,而且将使用相同的标志(--experimental-modules)。咱们但愿这个新实现可以解决社区的许多问题,而且可以在2019年10月Node.js 12达到LTS状态以前做为Node.js的一部分正式发布(不须要再带--experimental-modulesgithub

--experimental-modules包含了什么

与以前的版本同样,这个新的实验性模块为Node.js增长了如下支持:npm

  • ES2015 import语句能够引用那些使用ES模块语法编写的Javascript文件。文件能够被引用为相对url ('./file.mjs ')、绝对file:// url ('file:///opt/app/file.mjs ')、包名(' es-module-package ')或包名路径('es-module-package/lib/file.mjs ')的形式。json

  • import语句引用的ES模块文件能够指定默认导出(import _ from ‘es-module-package’)、命名导出(import { shuffle } from ‘es-module-package’) 和命名空间导出(import * as fs from ‘fs’)。全部的Node.js内置模块(如fs和path)都支持这三种类型的导出。api

  • import语句引用CommonJS文件(当前全部使用require、module.exports编写的Node.js模块)只能使用CommonJS默认导出(import _ from ‘commonjs-package’)。这项工做在进展中而且将来可能会发生改变promise

  • ES模块文件中的export语句能够指定引用的导入语句为默认导出或命名导出。

  • 动态import()表达式能够用来从CommonJS或者ES模块导入ES模块文件。须要注意的是,这个语句返回的是一个promise

  • import.meta.url的值为当前ES模块文件的绝对url。

  • 能够编写加载器(Loaders)来修改Node.Js对于ES模块的行为。这项工做仍然在进行中

  • Node.js能够将ES模块文件做为程序的初始入口运行

  • 文件做为ES模块被加载是在严格模式下的,若是是CommonJS的话须要在每一个文件的最头部加上'use strict'

  • .mjs结尾的文件在import语句和经过node命令行运行时都将被显式看成ES模块

而且,新版本的 --experimental-modules 添加了如下特性:

.js文件中的import和export语法

咱们听到了一些很是强烈的反馈Nodejs须要提供一种方式在.js文件中使用import和export语法

新的--experimental-modules提供了两种方式实现,一种是经过package.json中的type字段,另外一种是输入经过传入参数--eval, --print or STDIN添加一个--input-type标示

package.json type 字段

在你的项目package.json中添加'type':'module'字段,Node.js就会把项目中全部的.js文件看成ES模块

若是项目中的一些文件使用了CommonJS而且你不能当即转换它们,你能够把那些文件重命名为.mjs或者把它们放到一个子文件夹而后添加一个package.json包含{ “type”: “commonjs” },这样那些.js文件会被看成CommonJS处理

当Node.js想要加载任何文件的时候,它将会查找文件当前目录下的package.json文件,找不到的话将向上查找直到根目录。这种行为很是相似于babel的.babelrc文件。这种新的方式容许nodejs使用package级别的元数据和配置,相似于babel和其它工具目前使用的样子

--input-type flag

使用-—input-type=module做为ES模块运行字符串输入(-—eval、-—printSTDIN)。—-input-type的值为-—input-type=module—input-type=commonjs

.cjs扩展名

只有.mjs文件扩展名被看成ES模块,新的.cjs文件扩展名将被看成CommonJS模块。.cjs扩展名是当.mjs和.js看成es模块的时候,保留项目中的CommonJS文件用到的。

显式文件名

默认状况下在新的--experimental-modules下,import语句中的文件扩展名是强制性的:import ‘./file.js’并不一样于 import ‘./file’。可是,CommonJS风格的自动扩展名处理行为能够经过--es-module-specifier-resolution=node来开启(默认是es-module-specifier-resolution=explicit)。包名引入仍然不变,例如import fs from ‘fs

咱们提供了--es-module-specifier-resolution=node可选使用Commonjs风格扩展名和的解析。可是咱们默认关闭了它,在咱们去除--experimental-modules以前,用于收集用户对于彻底指定路径(fully specified paths)的反馈。 你能够在这里找到关于这个话题的讨论。

这种设计的主要缘由是,经过咱们提供的特定解决办法,去鼓励开发者们编写浏览器和node共享的代码

module.createRequireFromPath

CommonJS的全局变量(如require, exports, module, __filename, __dirname)在ES模块中将不会定义。可是可使用module.createRequireFromPath()去创造一个commonJS require函数在ES模块上下文中使用

只能引入Javascript

之前的--experimental-modules 容许导入JSON语句和原生模块。如今这个已经删除了,默认不能导入JSON语句和原生模块,您可使用module.createRequireFromPath()来实现原先的功能。

实验性标记--experimental-json-modules能够支持json文件的导入。咱们正在用浏览器对这个特性进行标准化,而且Node.js但愿咱们的支持能与最终的标准保持一致。

其它也有正在进行的工做,以涵盖WASM和其余将来潜在的模块类型。Node.js之后将以符合规范的方式增长对这些模块类型的支持。

npm包中的ES模块代码

这是一项正在进行的工做,可能会发生变化。经过package.jsonmain字段类型指定入口文件(这个文件是ES模块)。你可使用ES模块建立一个包。若是文件扩展名是.mjs或者package.json包含'type':'module'Node.js的话,Node.js将它做为ES模块加载。

目前,没法建立一个既能够经过require('pkg')又能够import ‘pkg’来使用的npm包。咱们正在努力解决这一问题,而且可能有对上述内容的修改。特别是,Node.js可能会选择'main'之外的字段来定义包的ES模块入口点。但咱们意识到社区已经接受了'main'字段,因此这也不太可能这样作由于不少包已经使用了module去引入ES模块的javascript,但可能没有评估在node.js中使用(由于文件名的扩展缺省的,或者代码里面包含require表达式)。在解决这个问题以前,请不要发布任何打算给Node.js使用的ES模块的npm包。

工做进展

上面全部的这些都是做为Node.js 12 --experimental-modules的一部分。在咱们的规划中,在 2019年10月 Node.js 12 达到 LTS 并移除--experimental-modules标识以前,咱们但愿有一些潜在的改进:

  • 加载器(Loader)功能。加载器正在进一步开发以支持进程隔离、多加载器和具备较低级别hook的多领域支持。在标记移除以前,--loader API仍然会有很大的变化。
  • 双重的CommonJS/ES模块包。咱们但愿为包做者提供一种标准的方式来发布一个包,这个包既能够被require到CommonJS,也能够被import到ES模块中。
  • 更容易的require。使用Module.createRequireFromPath()包含许多的模版文件。咱们但愿提供一种更简单的方式在ES模块代码中进行require
  • 包路径映射(原文:Package path maps).咱们想要提供一种包内路径到文件的映射。例如容许像import sdk from ‘some-service/sdk’‘some-service/sdk’./src/sdk/public-api.mjs的。
  • 自动入口点模块类型检查。这将提供一种方式来基于静态分析运行Javascript代码(CommonJS或ES模块)

就是这样!咱们但愿你喜欢这个新的--experimental-modules,并期待您的反馈。模块团队的工做在github.com/nodejs/modu…公开。

相关文章
相关标签/搜索