久々にJavaScript/TypeScriptを触ってみたら、モジュールシステムがESM〈ECMAScript Modules〉方式とCJS〈CommonJS〉方式のニ種類があって、ややこしく鬱陶しい状況になっているのね。これはフラストレーションがたまりますな。
モジュールとか存在しなかった“いにしえのJavaScript”においても、方言があったり処理系により機能・挙動が違ったりとかで、単一の言語とは言い難かったですが、モジュールシステムに関しては二大派閥みたいな感じで、「分離しちまっているな」という印象。
あくまで気持ち〈心的態度〉の問題ですが、「今のJavaScriptは2つの言語になってしまった」と捉えたほうが精神安定には良い(腹も立たない)と思います。ひとつは ECMAScript 2015 以降の言語 ES2015+、もうひとつは CommonJS 言語です。
異なる2つの言語があるんだなと思えば、色々と合点がいきます。
ソースファイルの拡張子は、ES2015+ は .mjs
、CommonJS は .cjs
です。なにしろ異なる言語だから同じ拡張子ってわけにはいかない。んじゃ、.js
は何? これは分からない。分からないので、拡張子とは別な方法で判別します。
- node.js : package.json において
"type": "module"
なら ES2015+。"type": "commonjs"
なら CommonJS。 - TypeScript : tsconfig.json において、
"module": "es2015"
(または、es2015 より後のバージョン)なら ES2015+。"module": "commonjs"
なら CommonJS。 - ブラウザ : script タグにおいて、
type="module"
なら ES2015+。nomodule type="text/javascript"
なら CommonJS(あるいは“いにしえのJavaScript”)*1。
*1:[追記]nomoduleは、CommonJS用の指示ではなくて、「ES2015+ に準拠したブラウザは無視せよ」という指示ですね。ESM2015+ を知らないブラウザは、nomodule属性も知らないので無視しないで解釈します。[/追記]