LoginSignup
0
0

ESModuleとCommonJSについてまとめてみた

Posted at

背景

現在開発しているPJはフロントエンドをAngular、バックエンドをNode.jsで実装している。Node.jsはTypeScriptで実装している。まだ勉強中の身なので環境構築時には意識したことがなかったが、同じTypeScriptなのにモジュールをインポートしたりエクスポートする際の記述の方法が異なっていたので気になって調べたところ、ESModulesとCommonJSというものに出会ったので、理解を整理するためにまとめる。

ESMoudlesとCommonJSの違い

それぞれの違いについてまとめる。

構文の違い

以下のような書き方の違いがある。

ESModules

// モジュールのエクスポート
// moduleA.mjs
export const add = (a, b) => a + b;

// モジュールのインポート
// main.mjs
import { add } from './moduleA.mjs';
console.log(add(3, 5)); // 8

CommonJS

// モジュールのエクスポート
// moduleA.js
const add = (a, b) => a + b;
module.exports = add;

// モジュールのインポート
// main.js
const addFunction = require('./moduleA.js');
console.log(addFunction(3, 5)); // 8

実行環境

ESModules

ブラウザやNode.jsの新しいバージョンではサポートされている。以下のサイトでブラウザごとの対応状況を確認できる。

CommonJS

 Node.jsではデフォルトで採用されているが、ブラウザではサポートされていない。ただ、Node.js上で動作するテンプレートエンジン(ejsやpugなど)を使用すればもちろんビューを作成し、ブラウザ上で動作させることが可能である。

モジュールの読み込み

ESModules

非同期でモジュールを読み込む。アプリケーションのパフォーマンス向上につながる。

CommonJS

同期的にモジュールを読み込む。そのため、複数のモジュールの読み込みが並行して行われることはなく、1つずつ順番に読み込まれる。

静的解析ができるか

ESModules

静的解析が可能。そのため、モジュールのパスに誤りなどがあれば、コンパイル時に指摘することが可能。

CommonJS

静的解析が不可能。

なぜ二つが存在するのか

そもそもなぜこのように2つのモジュールが存在するのか。これを理解するにはJavaScriptにおけるモジュールシステムの歴史を学ぶ必要がある。こちらで詳しく書かれているので、詳細は以下の記事に任せる。

ESModulesとCommonJSの統合

ESModulesとCommonJSが混同したPJの場合、フロントを実装する時とバックを実装するときで記述方法が異なったりするので、個人的にはどちらかに統一したいと思った。ここまで書いてきた通り、ESModulesの方が静的解析が可能だったり、Node.jsもESModulesをサポートし始めたことから潮流はESModulesに来ている。

Angularなどのフロントエンドフレームワーク、最新のNode.jsに関してはデフォルトでESModulesなので気にする必要はないが、古いバージョンのNode.jsを使用する場合には、以下のような手順でコンバージョンする必要がある。

引用元
https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#how-can-i-move-my-commonjs-project-to-esm

以下Google翻訳

CommonJS プロジェクトを ESM に移動するにはどうすればよいですか?
x"type": "module"package.json に追加します。
package.json 内"main": "index.js"の に置き換えます。"exports": "./index.js"
"engines"package.json のフィールドを Node.js 16: に更新します"node": ">=16"。
'use strict';すべての JavaScript ファイルから削除します。
require()すべての/を/module.exportに置き換えます。importexport
インポートには完全な相対ファイル パスのみを使用します: import x from '.';→ import x from './index.js';。
TypeScript 型定義 (たとえば、index.d.ts) がある場合は、ESM インポート/エクスポートを使用するようにそれを更新します。
Node.js 組み込みインポートのnode:プロトコルを使用します。

これを見た感想としては、

  • requireをimport fromに書き換えたり、module.exportsの書き換えが重い。
  • CommonJSではモジュールのパスを拡張子まで含めて書いていないと思うので、相対パスで拡張子まで含めて書くのはとても重い。
  • 依存パッケージがESModulesをサポートしている必要があるので、それの確認が重い。

実際にESModulesに移行している記事を調べてみるとこれ以外にもいろんな障壁があるらしい。

PJの規模にもよるだろうが、移行するのはめっちゃしんどそうというのが、個人的な感想である。1から作るときはNode.jsで最初からESModulesを使おうと思った。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0