さて一方で 2009 年に Kevin Dangoor により Web ブラウザ以外の実行環境における JavaScript 仕様を策定するプロジェクト CommonJS が立ち上げられます。CommonJS プロジェクト立上げを宣言した Kevin Dangoor のブログ記事の中でも他のモジュールを取り込む標準的な方法が言語として定められていないことを問題点の一つとして挙げています。
JavaScript needs a standard way to include other modules and for those modules to live in discreet namespaces. There are easy ways to do namespaces, but there’s no standard programmatic way to load a module (once!). This is really important, because server side apps can include a lot of code and will likely mix and match parts that meet those standard interfaces.
- What Server Side JavaScript needs
If the nearest parent package.json lacks a "type" field, or contains "type": "commonjs", .js files are treated as CommonJS. If the volume root is reached and no package.json is found, .js files are treated as CommonJS.
- Modules: Packages | Node.js v22.6.0 Documentation
Deno by default standardizes the way modules are imported in both JavaScript and TypeScript using the ECMAScript module standard.
- ECMAScript Modules in Deno
Node.js で ES モジュールを使用するには以下の通り拡張子を .mjs にするか、package.json の type フィールドに module を設定する必要があります。あるいは Node.js コマンドラインオプションの --input-type で module を指定するか、--experimental-default-type で module を指定する必要があります。
Authors can tell Node.js to interpret JavaScript as an ES module via the .mjs file extension, the package.json “type” field with a value "module", the --input-type flag with a value of "module", or the --experimental-default-type flag with a value of "module". These are explicit markers of code being intended to run as an ES module.
- Modules: ECMAScript modules | Node.js v22.6.0 Documentation
SyntaxError: Named export'helloWorld' not found. The requested module './module.js' is a CommonJS module, which may not support all module.exports as named exports.
すべて ES モジュールを使っていて CommonJS モジュールの混在がない場合は、 package.json で "type"="module" を指定する方が簡単です。この場合、拡張子は js のままでも ES モジュールとして扱われます。
package.json
{"type":"module"}
他にコマンドラインオプション --experimental-default-type に "module" を指定することで、拡張子は js のままでも ES モジュールとして扱われます。
上記 HTML を HTTP サーバにホストしてブラウザでアクセスするとコンソールに以下のエラーが出ます。
Uncaught SyntaxError: Cannot use import statement outside a module
ブラウザベースで ES モジュールを使用するには以下の通り、<script> タグの type 属性に module を指定する必要があります。ブラウザベースで ES モジュールを使用するにはこれが唯一の方法で、Node.js のように拡張子を .mjs にすると ES モジュールとして扱ってくれるとかはありません。
Access to script at 'file:///path/to/module.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome-untrusted, https, edge.
node index.mjs
Hello
(node:33604) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time(Use `node --trace-warnings ...` to show where the warning was created)