開発者ドキュメント

Nodev12の新しいECMAScriptモジュールの概要

###はじめにReactやAngularなどの一般的なJavaScriptフロントエンドフレームワークに精通している場合、ECMAScriptの概念はまったく新しいものではありません。 ESモジュールには、フロントエンドフレームワークでよく見られるimportおよびexport構文があります。 **ノードはインポートにrequire()に依存するCommonJSを使用します。 require()に加えて、Nodeでインポートとエクスポートを使用できるようになりました。 新しいNodev12リリースに付属しているのはそれだけではありません。期待できるすべての新しいクールな機能について話しましょう。

新しいESモジュール

これまで、以前のNodeリリースには、ECMAScriptモジュールの実験的なサポートが付属していました。 このサポートは--experimental-modulesフラグの背後にあり、現在もそうですが、前回のリリース以降、多くのことが行われており、次のリリースに満足しています。 前回のリリースから提起された懸念事項とフィードバックの一部が実行され、次のリリースで実現されることを私たちは知っています。

Node.jsは、.jsファイルでインポートおよびエクスポート構文を使用する方法を提供する必要があるという優れたフィードバックがあります。 新しい--experimental-modulesでは、これに対して2つの方法が提供されています。

  1. 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の優先順位が機能する方法と考えることができます。これは、ツリーを子から親に至るまでカスケードします。

  1. --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つのモジュールタイプがあります。

  1. CommonJSモジュールタイプ
  2. 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つの方法があります。

  1. node index.js --experimental-modules
  2. 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の代替手段と比較して、それが何を提供するかを理解するために、それを詳しく調べました。

モバイルバージョンを終了