Open9

Node.js向けライブラリのpublishの仕方を再勉強

hashrockhashrock

実際Node.jsのesm対応その他についての自分の知識が古いなと思ったのでアップデートを試みる。

hashrockhashrock

package.jsonについて。

mainフィールドはCJSのエントリポイント。
moduleはESM配布の際のエントリポイント。分かりづらい。

https://qiita.com/zprodev/items/e2f7e24acf0ca1227e13

Node.jsでもブラウザ(+バンドラ)でも現状CJSの配布を行うのが普通である。
併せてESMも配布すると対応バンドラではTree Shakingをかけられる。

hashrockhashrock

UMDってそもそも何だっけという話。

https://github.com/umdjs/umd

Q promiseライブラリ(聞いたことあると思う)で使われていたテクニックをパターン化したものらしい。

https://wolfbash.hateblo.jp/entry/2022/11/17/150227

やっていることは概ねブラウザではwindowにモジュールをぶら下げる、またはNode.jsの場合はエクスポートするだけ。

概ねUMDはCDN経由でシンプルなライブラリを配布したいなら出力する、くらいの理解で良さそう

hashrockhashrock

今のところまでの理解:

  • Node.js向けであればCJSのみ、またはCJS, ESMの両方を出力する
    • CJSだけでも、ESM側からはimportで読み込めるので問題ない(し、Tree shakingはNode.jsからのメリットは大きくない)
    • ESMだけは今のところNG。CJSを用意しないと利用側もESMに移行しないといけなくなる
  • Node.jsとブラウザ両対応では、CJS, ESMの両方を出力する。
    • 利用側のコードがESMであるとは限らないが、可能性は高い
    • 特にブラウザ側ではTree shakingの需要があるため、両方用意したほうがよい
    • Node.jsからも使われることを考えると引き続きCJSも提供したほうが良さそう
  • CDN経由でも使えるようにするにはバンドル済みESMとUMD両方を提供する。ブラウザ側でtype="module"の中で使いたいケースと、そうでないケースの両方がありうるため。
hashrockhashrock

例外があった。Node.jsでCJSプロジェクトからESM実行できるのか…

https://www.wantedly.com/companies/wantedly/post_articles/410531

Top level await本当に必要だった?みたいな話がようやく理解できた。自分もTop level awaitよりCJSからのESMインポートを優先したほうが良かったんじゃないのと普通に思った

hashrockhashrock

というかFake ESMというのがあるのか。頭痛くなってきた…
Fake ESMはESMの文法を使えるものの、バンドラでCJSにトランスパイルされるのが前提となる。そのためimportでファイル名を省略できたりする(Native ESMのモジュール解決ではない)

なのでFake ESMとNative ESMは明確に区別しなくてはいけない。