JS モジュール化#
#フロントエンド / JS
Common JS#
- モジュールは複数回読み込むことができ、最初の読み込み時にのみ実行され、実行結果はキャッシュされ、モジュールを再度実行するにはキャッシュをクリアする必要があります。
- 同期的に読み込まれ、モジュールの読み込みは後続のコードの実行をブロックします。
- サーバー環境(nodejs)で使用されます。
exports
はmodule.exports
への参照にすぎません。つまり、Node は各モジュールにexports
変数を提供し、それがmodule.exports
を指すようにします。つまり、各モジュールの先頭には次のようなコードがあるということです。
var exports = module.exports
モジュールのエクスポートとインポート
// common-js-a.js モジュールのエクスポート
// デフォルトで var exports = module.exports が追加されます
exports.a = 'hello world';
// common-js-b.js モジュールのインポート
const moduleA = require('./common-js-a');
console.log(moduleA.a)
AMD#
- 非同期に読み込まれます。
- ブラウザ環境で使用され、前提となる依存関係があります。
// a.js モジュールのエクスポート、module1とmodule2は他の前提依存関係です
define(['module1', 'module2'], function (m1, m2) {
return { a: 'hello world' };
})
// b.js モジュールのインポート
require(['./a.js'], function (moduleA) {
console.log(moduleA.a)
})
CMD#
- ブラウザ環境で使用されます。
- 非同期に読み込まれ、近くの依存関係があります。
// 非同期に読み込まれ、近くの依存関係があります
// a.js のエクスポート
define(function(require, exports, module) {
exports.a = 'hello CMD'
})
// b.js のインポート
define(function(require, exports, module) {
var moduleA = require('./a.js') // 近くの依存関係
console.log(moduleA.a)
})
UMD#
AMD、CommonJS、グローバルな参照の両方に対応
ブラウザと Node の両方で実行できます
(function webpackUniversalModuleDefinition(root, factory) {
// テストコメント
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require('lodash'));
// テストコメント
else if(typeof define === 'function' && define.amd)
define(['lodash'], factory);
// テストコメント
else if(typeof exports === 'object')
exports['someLibName'] = factory(require('lodash'));
// テストコメント
else
root['someLibName'] = factory(root['_']);
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
// ...
});
ES6 モジュール#
// a.js
export const a = 'hello es6 module'
// b.js
import { a } from './a.js'
- ブラウザ環境では、現在も ES5 コードに変換するために Babel が必要です。
- export はオブジェクト形式のエクスポートのみをサポートし、値のエクスポートはサポートされていません。export default はデフォルトの出力を指定し、本質的には default という名前の変数です。
結論#
- CommonJS の同期的な読み込みメカニズムは主にサーバーサイド、つまり Node で使用されますが、それに伴うブロッキングロードの特性はブラウザリソースのロードには適用されないため、AMD、CMD の仕様が生まれました。
- AMD と CMD はどちらもブラウザでモジュールを非同期に読み込むことができますが、実際にはこれらの仕様の開発コストはかなり高いです。
- UMD は AMD、CommonJS、グローバルな参照など、さまざまな仕様に対応しており、現在の JS ライブラリのパッケージングの主流と言えます。
- ES6 は言語の標準レベルでモジュール化を実現し、非常に使いやすくなりました。現在、ブラウザ側の標準的なソリューションと言えるでしょう。さらに、現代のパッケージングツールのサポートを受けることで、Node サーバーサイドの支配も目前です。