 
   Node.jsの新しいモジュール方式の実験的導入
目次
Node.js の Core へ ESM と CJS の新しい方式が実験的フェイズ(stability: 1)として入ります。
ESM 対応は安定化までのプランとしてステージを 4 つ(0 -3)用意しており、現在が 2 です。
modules/doc/plan-for-new-modules-implementation.md at main · nodejs/modules
Node.js Modules Team. Contribute to nodejs/modules development by creating an account on GitHub.
2019 年の 10 月に実験的から安定的へ移行するのが最終目標となります。(stage:3)
内容まとめ
- --es-module-specifier-resolution=node|explicitで処理解決方法を決定する- explicitがデフォルト
 
- --entry-type=commonjs|moduleで CJS か ESM かを決定する- デフォルトは近しい親にある package.json のtypeフィールドを参照する
 
- デフォルトは近しい親にある package.json の
- ESM ではデフォルトで json は読み込めない
- --experimental-json-modulesを付ける必要がある
 
- CJS と ESM の違い
- ESM の場合、拡張子が必須
- NODE_PATHがない
- require,- exports,- module.exports,- __filename,- __dirnameがない-  module.createRequireFromPath、及びimport.meta.urlを使いましょう
 
-  
- require.extensions,- require.cacheの使用不可
- URL-based のパス指定
 
とりあえず、package.json にtypeフィールド追加すると、そのスコープ内の.jsファイルはそのモジュールタイプになるよって覚えておけばいいです。
ESM 事前知識
以下の記事を読んでください。
Node.jsとECMAScript Modules - hiroppy's site
Node.jsに入るECMAScript Mdoulesの特徴を紹介します
 
 PR
Core への PR
new ESM implementation by MylesBorins · Pull Request #26745 · nodejs/node
This PR updates the current --experimental-modules implementation based on the work of the modules team and reflects Phase 2 of our new modules plan. A longer form description of these changes can ...
初期提案実装
Entry points proposal spec and implementation by guybedford · Pull Request #32 · nodejs/ecmascript-modules
This implements a top-level --type flag for --experimental-modules with the following behaviours. In addition "type": "esm" in the package.json is renamed to "type": &...
—es-module-specifier-resolution
explicit と node が存在し、デフォルトはexplicitです。
違いは以下の通りとなります。
- 拡張子を省略することができない
- indexを許容しない
まだ、変更される可能性が高いため注意が必要です。
今までどおりの挙動を望むのであれば、nodeを指定する必要があります。
リゾルバアルゴリズム
typeフラグがmoduleの場合、package.json を軸に次の package.json までにネストされたフォルダとサブフォルダをすべて ESM とみなす仕様(そしてつぎ package.json のフラグがmoduleの場合は続く)
もし package.json がない場合は、デフォルトで commonjs となります。
Node.js Package Mode について - hiroppy's site
Node.jsに新しく入る可能性があるpackage modeについて紹介します
 
 使用法
実験的なフェイズなため、実行時に--experimental-modulesフラグが必要です。
.mjsがエントリーポイントの場合
この場合は、デフォルトで ESM として読み込みます。
node --experimental-modules index.mjsまた、上記の実行の場合、エントリーポイントから ESM 形式で import するファイルは.mjsである必要があります。
しかし、--entry-typeフラグ及び、package.json のtypeにmoduleを指定すると、.mjsという拡張子を使うことなく、ESM として読み込むことが可能となります。
{  "type": "module"}—entry-type
このフラグには、commonjsとmoduleの 2 つの設定が存在します。
moduleが指定された場合、.js, .mjs, 拡張子がないファイルは ESM として呼び出されます。
この指定がない場合、デフォルトはcjsです。
$ node --experimental-modules --entry-type=module --eval \  "import { sep } from 'path'; console.log(sep);"/from 'path'; console.log(sep);"
import { sep } from 'path'; console.log(sep);       ^
SyntaxError: Unexpected token {package.json の type フィールド
--entry-typeの package.json に書く版です。
最も近い親の package.json のtypeフィールドを参照し、モジュール方式を決定していきます。
一般的に今までの node_modules の package.json はtypeフィールドを持たないため、commonjs で読み込まれ互換性を保つことが期待されます。
{  "type": "module"}// 近しいpackage.jsonのtypeがmoduleなので、このファイルはESMで読み込まれるimport "./sample/setup/init.js";
// ./node_modules/foo/package.jsonにはtypeが書いてないため、CJSで読み込まれるimport "foo";特定ファイルのモジュール形式をロックしたい場合
ユーザーが表現できる拡張子は、.js, .mjs, .cjsとなります。
type: module|commonjs以下では、.jsはそれに従います。
つまり、特定のファイルに対して拡張子で操作することになります。
- type:module以下で commonjs として扱いたいファイルに対しては、- .cjsの拡張子にする
- type:commonjs以下で esm として扱いたいファイルに対しては、- .mjsの拡張子にする
// 常にcommonjsとして読み込むimport "./legacy-file.cjs";
// 常にesmとして読み込むimport "commonjs-package/src/index.mjs"; 
   
  