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…公開。

相關文章
相關標籤/搜索