自分的ESM(ES Modules)対応方法
はじめに
ゴシップサイトブロッカー他ES Modules(ESM)に対応するのをいろいろやってきたり、最近Node.js関連の開発が多くていろいろ試行錯誤した結果、こうしたらいいのかなぁというのを自分なりにまとめてみます。あくまで利用者視点なので、ライブラリの作成者には役立ちません。あとNode.jsを前提にしています。
原則
ES Modules対応するときにはまず「CommonJSでは書かない」というのを原則としています。 当たり前と言えば当たり前なんですが、とにかく「CommonJSでは書かない」というのは大前提です。 なので以下の話は全て「CommonJSでは書かない」という話です。
CommonJS前提のライブラリやツールを選ばない
一番重要なのはライブラリやツールの選定です。 CommonJSでしか使えないライブラリやツールを最初から選ばないことです。
といってもライブラリは基本的にCommonJSで例が書かれていても、ESMで書けます。 require記法をimport記法に変えればそのまま動くものがほとんど(全部?)です。
あとloadshはlodash-esがあるのでこちらを使いましょう。適切に使えばTree Shakingが効いてサイズも小さくなります(lodash自体をやめる話もあるがそれは別の話)。
しかし最終的にこの2つのツールは乗り換えました。
- Jest → Vitest
- ts-node → tsx
特にJestはIssueにありますが、mockが使えないのが致命的です。 頑張るよりVitestに乗り換えたほうが絶対いいです。
ts-nodeもtsxに乗り換えたほうが幸せになれると思います。watchモードがあるのもいいです。
一部の定数は回避策を適用
__dirname
, __filename
が使えない問題は回避策があります。
設定ファイルのみは例外で .cjs
にする
そもそもCommonJS前提のライブラリやツールを選ばないのですが、例外は一部のツールの設定ファイルです。 具体的にはESLintやdependency cruiserが該当します。
これらの設定ファイルはCommonJSの module.exports
を使っていますが、拡張子を .cjs
にすることで回避しています。
設定ファイルは独立しているのと、対応できないものも多いので。
それでも次のエラーが出ますが、これは // eslint-disable-next-line no-undef
として無視させています。
path/to/.eslintrc.cjs
1:1 error 'module' is not defined no-undef
なお、ESLint v9からの新しい設定ファイルは、ESM形式でも書けるようになっています。
package.json は type: module
にする
これでデフォルトがESMになります。
おわりに
これくらいしか書くことがないです。逆に言えば、もう悩むことがほとんどなくなったかなと思います。
←コロナワクチン4回目を受けた