Nodev12の新しいECMAScriptモジュールの概要
- はじめにReactやAngularなどの一般的なJavaScriptフロントエンドフレームワークに精通している場合、ECMAScriptの概念はまったく新しいものではありません。 ESモジュールには、フロントエンドフレームワークでよく見られる
import
およびexport
構文があります。 **ノードはインポートにrequire()
に依存するCommonJSを使用します。require()
に加えて、Nodeでインポートとエクスポートを使用できるようになりました。 新しいNodev12リリースに付属しているのはそれだけではありません。期待できるすべての新しいクールな機能について話しましょう。
- はじめにReactやAngularなどの一般的なJavaScriptフロントエンドフレームワークに精通している場合、ECMAScriptの概念はまったく新しいものではありません。 ESモジュールには、フロントエンドフレームワークでよく見られる
新しいESモジュール
これまで、以前のNodeリリースには、ECMAScriptモジュールの実験的なサポートが付属していました。 このサポートは--experimental-modules
フラグの背後にあり、現在もそうですが、前回のリリース以降、多くのことが行われており、次のリリースに満足しています。 前回のリリースから提起された懸念事項とフィードバックの一部が実行され、次のリリースで実現されることを私たちは知っています。
Node.jsは、.js
ファイルでインポートおよびエクスポート構文を使用する方法を提供する必要があるという優れたフィードバックがあります。 新しい--experimental-modules
では、これに対して2つの方法が提供されています。
package.json
に“type” : “module”
を設定します
// package.json { "type": "module" }
これにより、Node.jsは、プロジェクト内のすべての.js
ファイルをESモジュールとして扱うようになります。 モジュールとして扱いたくないCommonJSファイルがまだある場合は、それらの名前を.cjs
ファイル拡張子に変更できます。これにより、Node.jsにそれらをCommonJSとして明示的に解析するように指示されます。 または、すべてのCommonJSファイルをpackage.json
ファイルと"type":"commonjs"
を含むサブフォルダーに入れることができます。このサブフォルダーでは、すべての.js
ファイルがCommonJSとして扱われます。
最も近い親のpackage.jsonファイルに
type
フィールドがない場合、または"type": "commonjs"
が含まれている場合、拡張子のない.jsファイルはCommonJSとして扱われます。 ボリュームルートに到達し、package.jsonが見つからない場合、Node.jsはデフォルトに従い、.jsの"type" field.import
ステートメントがないpackage.jsonと拡張子のないファイルは、最も近い親がESモジュールとして扱われます。 package.jsonには"type": "module"
が含まれています。
このタイプと拡張機能のスコープは、CSSの優先順位が機能する方法と考えることができます。これは、ツリーを子から親に至るまでカスケードします。
--input-type flag
を使用してください
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
インポートおよびエクスポート構文を使用する2番目の方法は、--input-type=module
を使用して文字列入力を(--eval
、--print
、またはSTDIN
を介して)ESとして実行することです。モジュール。 --input-type
フラグは、--input-type=module
または--input-type=commonjs
のいずれかになります。 この場合、CommonJSではなくモジュールに設定しているため、より早くなります。
より期待されるWIP機能
Node.jsモジュールチームがまだこれらの機能に取り組んでいることを考えると、既存の機能として正確に報告することはできません。 なんで? それらはまだ作業中であるため、おそらくすべてが変更される可能性がありますが、それらが何であるか、およびそれらがどのように動作する可能性があるかについてはわかっています。
モジュールローダー
非常にWIP機能。 --loader
APIの最初の実装が出荷されましたが、まだ作業中であるため、次のリリースで変更される可能性があります。
パッケージパスマップ
この機能はまだ出荷されていません。 これにより、モジュールのインポート方法が再定義され、特定の状況で冗長性の低いインポートが可能になります。
自動エントリポイントモジュールタイプの検出
この機能により、Nodeはプロジェクトに存在するモジュールのタイプを識別できるようになります。 出荷時に、Nodeは特定のモジュールがESモジュールであるかCommonJSモジュールであるかを知ることができます。
Node v12には他にも多くの新機能があります。Mediumのモジュールチームによる公式ブログ投稿で、お気軽に深く掘り下げてください。 それまでの間、Nodeにあるモジュールのタイプを詳しく見てみましょう。
ノード内のさまざまなタイプのモジュール
これはこの時点で明白に見えるかもしれませんが、私は経験を積んで、ほとんどの人がNodeにあるさまざまなタイプのモジュールを理解するのに苦労していることを理解するようになりました。 最近まで、Nodeで必要なのはCommonJS構文だけであることを考えると、混乱を招く人がいることは理解できます。
Nodeには2つのモジュールタイプがあります。
- CommonJSモジュールタイプ
- ESモジュールタイプ
- CommonJSモジュール
CommonJSモジュールは、Nodeに付属するデフォルトのモジュールです。 ESモジュールの開始前は、すべてのノードアプリケーションは、require()
およびmodule.exports
構文を使用してモジュールをプルしてエクスポートするCommonJSモジュール構造で動作します。 この例を考えてみましょう。
//src/main.js var products = require('src/products'); // import module
ここでは、products
モジュールをアプリのsrc
ディレクトリにある別のファイルからmain.js
ファイルにインポートしました。 先に進んで、現在のファイルのモジュールを自由に使用できます。 これはどのように可能ですか? CommonJSの仕様に従って、products
関数がsrc/products
ファイルのexportsオブジェクトに設定されているためです。
//src/products.js exports = function(){ return response.get('all-products); }
Node.jsの実装
Node.jsの実装は、上記のCommonJSで見たものとそれほど変わりません。 違いは、モジュールがホストファイルからエクスポートされる方法にあります。 CommonJSはexports
変数を使用してモジュールをエクスポートしますが、Nodeモジュールはmodule.exports
オブジェクトを使用します。
//src/products function products(){ return response.get('all-products); } modules.exports = products;
CommonJSの実装と同様に、これは同期プロセスであり、ファイルはファイル内に表示される順序で次々にロードされます。
- ESモジュール
ESモジュールは、CommonJSモジュールシステムの改善と見なすことができます。 CommonJSのrequire
の代わりにimport
およびexport
キーワードを使用するだけで、モジュールをインポートおよびエクスポートすることができます。 CommonJSとは異なり、ESモジュールは同期モードと非同期モードの両方の操作モードと互換性があります。
上記の前の例でCommonJSを使用して見た製品の例を考慮すると、次のようにESモジュールを使用してファイルをやり直すことができます。
//src/main.js import products from 'src/products'
前に説明したように、import
ステートメントは、モジュールを名前空間に取り込むために使用されます。 CommonJSのrequireの代替手段とほぼ同じように動作しますが、動的ではないため、ファイル内のどこでも使用できません。 繰り返しになりますが、このファイルはおそらくホストファイルからエクスポートされているため、ここで使用するためにインポートすることができました。
//src/products.js export function products() { return response.get('all-products); }
ここでのexport
ステートメントを使用すると、別のファイルからこの関数にアクセスできます。 簡単に言えば、機能を広く利用できるようにします。 この結果、静的アナライザーは、最終的にコードを実行する前に、ファイルをバンドルしながら最初に依存関係のツリーを構築します。 これは、ESモジュールを使用することの主な利点であると私は考えています。
過去のノードのESM
NodeのESモジュールの概念はまったく新しいものではなく、Node.js8.9.0が[の背後にあるインポートおよびエクスポートステートメントで知られるECMAScriptモジュールの実験的サポートを出荷した2017年から利用可能になっています。 X226X]フラグ。
ただし、この時点まで、この機能は実験的な状態のままです。 理由? Node.jsコミュニティがそれを使用し、その設計に関する実用的なフィードバックを提供できるようにするため。 それ以来、多くのことが起こりました。 主要なブラウザは、<script type="module">
を介してECMAScriptモジュール(ESモジュール)をサポートするようになりました。 ESモジュールソースを含むnpmパッケージが、<script type="module">
を介してブラウザーで使用できるようになりました。 インポートマップのサポート。これにより、import
ステートメントでNode.jsスタイルのパッケージ名がブラウザに提供され、がChromeに導入されます。 そして、他にもたくさんあります。
長い間待っていて、実験的なESM設計に関するフィードバックを受け取りました。また、ESモジュールが使用されているランタイムや環境が他にもあるため、Node.jsがこのESMJavaScript標準をサポートするのに今ほど良い時期はありません。 そしてこれが、モジュールチームがESモジュールをサポートするための新しい実装を発表した理由です。 彼らによると、Node.js 12の一部として出荷され、同じフラグの背後にある古い--experimental-modules
実装に取って代わります。
nvmを使用してv12を使い始める
ESMの長期的なサポートを待つ間、nvmを使用してESMの操作と機能に慣れることができます。 nvmを使用すると、1台のマシンに複数のバージョンのノードをインストールし、必要に応じてそれらを切り替えることができます。
つまり、現在Node v6またはv10を実行しているバージョンが何であれ、最新バージョンまたは古いバージョンに切り替えて、現在のバージョンとファイルをそのままにして試してみることができます。
nvm をインストールし、それを使用してNodeバージョンを管理し、現在のバージョンにはまだ存在しない MichaelWanyoikeのさまざまな機能を試す方法について説明したいと思います。 ]は、Sitepointのこの投稿ですでに素晴らしい仕事をしています。 さまざまなOSSプラットフォームでnvmがどのように機能するかを知りたい場合は、投稿にアクセスしてください。
—experimental-modulesフラグを使用して、LTSまでのインポートをサポートします
この投稿で前述したように、ESモジュールはしばらく前から存在しており、LTSまで使用するには2つの方法があります。
node index.js --experimental-modules
node --experimental-modules index.js
残念ながら、最初の方法、つまりnode index.js --experimental-modules
の使用は機能しないため、ノードアプリケーションでESMインポートをサポートするには、上記の2番目のオプションを使用する必要があります。
動的インポートはどこにも行きません
動的インポートは、着信ESモジュールの実装による脅威にさらされていないことに注意してください。 このESMの時代以前は、動的インポートにより、アプリケーション内のさまざまな場所からモジュールを動的にインポートして使用することができました。
動的インポートが要求されたモジュールのモジュール名前空間オブジェクトのpromiseを返す場合、async/await
および.then()
ベースのコールバックスタイルを使用して、ロードを可能にするすべてのモジュール動作を処理できます。モジュールを非同期的に。 これが私たち全員がそれを愛している理由であり、新しい実装でそれを失うことはないということを知っているのは良いニュースです。
JSONファイルのインポートはどうですか?
現在のところ、module
モードでは、JSONモジュールのインポートはそのままではサポートされていません。 ただし、commonjs
モードでサポートされており、CJSローダーを備えたローダーです。 とはいえ、現在、JSONインポートがmodule
モードでサポートされるようにするための取り組みが行われています。 たとえば、現在、 WHATWG JSONモジュールは現在標準化されており、Node.jsの実行時に追加のフラグ--experimental-json-modules
を含めることで実験的にサポートされています。
JSONインポートはcommonjs
モードですぐにサポートされますが、--experimental-json-modules
フラグが含まれている場合、commonjs
モードとmodule
モードの両方で新しい実験的なJSONローダー。
ただし、少し欠点があります。インポートされたJSONはdefault
のみを公開するため、現在、名前付きエクスポートはサポートされていません。 実験的なJSONローダーはcommonjs
モードよりも優先されるため、重複を避けるために、CommonJSキャッシュに個別のキャッシュエントリが作成されます。 JSONモジュールがすでに同じパスからインポートされている場合、同じオブジェクトがCommonJSに返されます。 以下の例を考えてみましょう。
import productsConfif from './package.json';
これが実際に機能するには、更新する必要があります
node --experimental-modules index.js
に
node --experimental-modules --entry-type=module --experimental-json-modules index.js
--experimental-json-modules
が使用できないため、以前のバージョンは失敗します。
最終的な考え
Node.jsv12に登場する新しいEcmaScriptモジュールについては多くの議論がありました。 この記事では、通常のCommonJSの代替手段と比較して、それが何を提供するかを理解するために、それを詳しく調べました。