@ledsun blog

Hのキーがhellで、Sのキーがslaveだ、と彼は思った。そしてYのキーがyouだ。

npmにESモジュールとCommonJSモジュールを両方公開すること

Node.js 12からESモジュールがサポートされています。 ブラウザでもESモジュールをサポートしています。 ということで、Node.jsむけのパッケージもESモジュールで書きたいです。

自分がESモジュールで書くと言うことは、依存ライブラリもESモジュールで書かれていて欲しいです。 しかし、自分の作ったnpmパッケージのユーザーがESモジュールを使っているとは限りません。

つまりnpmパッケージ作成者としては、1つのパッケージの中で、ESモジュールとCommonJSモジュールの両方のモジュールをpublishしたいです。 かつ、npmパッケージのユーザーとしては、npmパッケージがどちらのモジュールで公開されていることは気にしたくないです。 このような要望に応える為に、Conditional Exports という機能があります。

Node.js Dual Packages (CommonJS/ES Modules) に対応した npm パッケージの開発 - Cybozu Inside Out | サイボウズエンジニアのブログ

Conditional Exports という機能を使うことで、内部のファイルを参照せずに ESM、CJS 両方からパッケージを使うことができるようになります。

https://nodejs.org/api/packages.html#packages_conditional_exports

具体的には、package.jsonに次のようなプロパティを追加します。

  "exports": {
    "import": "./index.mjs",
    "require": "./index.cjs"
  },

というわけで、自作のnpmパッケージを次の手順で開発できます。

  1. ESモジュールで書く
  2. ESモジュールのままテストする
  3. ESモジュールからCommonJSモジュールを生成する
  4. ESモジュールとCommonJSモジュールを両方公開する

次に気になるのは、3の「ESモジュールからCommonJSモジュールを生成する」です。

参考