CommonJS、AMD、およびRequireJSの関係は?


840

たくさん読んだ後でも私はCommonJS、AMD、およびRequireJSについてまだ非常に混乱しています。

CommonJS(以前のServerJS)は、言語がブラウザーの外部で使用される場合にJavaScript仕様(モジュール)を定義するためのグループであることを知っています。CommonJSモジュールの仕様には、Node.jsRingoJSなどの実装がありますよね?

CommonJS非同期モジュール定義(AMD)、およびRequireJSの関係は何ですか?

あるRequireJSはの実装CommonJSのモジュール定義?はいの場合、AMDとは何ですか?


31
requirejs.org/docs/whyamd.htmlを読むと、それらすべてに言及しているため、多くのことが明確になります。(私はこれを完全な答えとは考えていないので、コメントとして投稿します)。
mmutilva 2013

5
質問や追加はできますか?ES2015のインポートステートメントはこれらのすべてにどのようにまたはどこに当てはまりますか たとえば、「ember」からEmberをインポートします。
testndtv 2016

(CommonJS、UMD、AMD、ES6)などのサポートされているJSモジュール形式をロードするsystemjsもあります。
アンディ

回答:


770

RequireJSAMD API (ソース)を実装します。

CommonJSは、exportsオブジェクトの助けを借りてモジュールを定義する方法であり、モジュールの内容を定義します。簡単に言えば、CommonJS実装は次のように機能する可能性があります。

// someModule.js
exports.doSomething = function() { return "foo"; };

//otherModule.js
var someModule = require('someModule'); // in the vein of node    
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };

基本的に、CommonJSは、require()依存関係をフェッチする関数、exportsモジュールの内容をエクスポートする変数、および依存関係を要求するために使用されるモジュール識別子(このモジュールに関連する問題のモジュールの場所を説明する)が必要であることを指定します(ソース)。CommonJSには、あなたが言及したNode.jsを含むさまざまな実装があります。

CommonJSは特にブラウザーを念頭に置いて設計されていなかったため、ブラウザー環境にうまく適合していません(私にはこれのソースはありません-RequireJSサイトを含めどこにでもそう言っているだけです非同期ロードなどを行う

一方、RequireJSはAMDを実装しており、これはブラウザー環境(ソース)に適合するように設計されています。どうやら、AMDはCommonJS Transportフォーマットのスピンオフとして始まり、独自のモジュール定義APIに進化しました。したがって、2つの間の類似点です。AMDの新機能はdefine()、モジュールがロードされる前に依存関係を宣言できるようにする機能です。たとえば、定義は次のようになります。

define('module/id/string', ['module', 'dependency', 'array'], 
function(module, factory function) {
  return ModuleContents;  
});

したがって、CommonJSとAMDはJavaScriptモジュール定義APIであり、実装は異なりますが、どちらも同じ起源のものです。

  • AMDは、モジュールの依存関係の非同期読み込みをサポートしているため、ブラウザにより適しています。
  • RequireJSAMDの実装であり、同時にCommonJSの精神(主にモジュール識別子)を維持しようとします。

さらに困惑させるのは、AMD実装であるRequireJSがCommonJSラッパーを提供するため、CommonJSモジュールをほぼ直接インポートしてRequireJSで使用できるようにすることです。

define(function(require, exports, module) {
  var someModule = require('someModule'); // in the vein of node    
  exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});

これが説明を明確にするのに役立つことを願っています!


7
2つの形式のギャップを埋めるuRequire.orgプロジェクトを確認してください-どちらか(または両方)で書き込み、2つまたは単純な<​​script>のいずれかにデプロイします
Angelos Pikoulas 2013

51
FYI Browserifyを使用すると、ブラウザーでCommonJSを使用できるようになります。
Eruant 2014年

9
@Eruantしかし、AMDほど非同期ではありません。
Inanc Gumus 2014

8
RequireJSのドキュメントに記載されているようにCommonJSがブラウザーに適合しない理由- 「CommonJS require()は同期呼び出しであり、すぐにモジュールを返すことが期待されています。これはブラウザーではうまく機能しません詳細はこちら
msenni 2015年

4
@aaaaaaユーザーの要求に応じて、いくつかの機能を有効にすることができます。そのため、AMDの非同期の性質が役に立ちます。
イナングムス

199

CommonJSはそれだけではありません。JavaScriptの共通のAPIとエコシステムを定義するプロジェクトです。CommonJSの一部はモジュール仕様です。Node.jsとRingoJSはサーバーサイドJavaScriptランタイムであり、どちらもCommonJS Module仕様に基づくモジュールを実装しています。

AMD(非同期モジュール定義)は、モジュールのもう1つの仕様です。RequireJSは、おそらくAMDの最も人気のある実装です。CommonJSとの大きな違いの1つは、AMDはモジュールが非同期でロードされることを指定することです。つまり、ロードの完了を待機することで実行をブロックするのではなく、モジュールが並列でロードされます。

このため、AMDは一般にクライアント側(ブラウザ内)JavaScript開発でより多く使用され、CommonJSモジュールは一般にサーバー側で使用されます。しかし、あなたはどちらの環境でいずれかのモジュールの仕様を使用することができます-例えば、RequireJS申し出のNode.jsの中で実行するための指示をしてbrowserifyは、ブラウザで実行することができますCommonJSモジュールの実装です。


20
なぜCommonJSのホームページがこんなに恐ろしいのか...私は公式の仕様を見ようとしているだけです。構文エラーがあり、ドキュメントが不完全で、Wikiページが解決されていません。
taco 2015年

7
これは、非同期でモジュールをロードすることを意味するものではありません。動的/遅延読み込みについて話しているかもしれません。非同期では、ファイルの読み込みを提案し、しばらくしてから、読み込みが完了したときにコールバックします。同期では、ロードするファイルを提案し、そのファイルのロードが完了するまでスレッド全体がブロックされます。ファイルが読み込まれるまで、それ以上のコードは実行されません。前者は予測不可能性を犠牲にしてより良いパフォーマンスをもたらすことができ、後者は毎回同じ結果をもたらすことができるため、より予測可能です。これらの癖は、さまざまな最適化を使用して軽減できることに注意してください。
ペリー

答えてくれてありがとう。ES2015のJSでモジュールが公式になりましたが、これはAMDまたは一般的なJSよりも優先されることを意味しますか?
Akhoy

それが好ましいという意味ではありません。それはすべて開発者のニーズ次第です。オプションを残してES6モジュールに移行することは、特に良い考えだとは思いません。ただし、優れたUMDを使用すると、その問題に対処できます。AMDと同期したCommonJSバンドルをロードすることは、一般に(パフォーマンス向上のため)良い(最良の)アイデアです。明らかに、もっとコントロールしたほうがいいと思うなら。そして、あなたはすべきです。
Maciej Sitko

187

短い答えは:

CommonJS AMDは、モジュールとその依存関係をJavaScriptアプリケーションで宣言する方法に関する仕様(または形式)です。

RequireJSは、AMD準拠のスクリプトローダーライブラリです。curljsもその1つの例です。

CommonJS準拠:

Addy Osmaniの本から引用。

// package/lib is a dependency we require
var lib = require( "package/lib" );

// behavior for our module
function foo(){
    lib.log( "hello world!" );
}

// export (expose) foo to other modules as foobar
exports.foobar = foo;

AMD準拠:

// package/lib is a dependency we require
define(["package/lib"], function (lib) {

    // behavior for our module
    function foo() {
        lib.log( "hello world!" );
    }

    // export (expose) foo to other modules as foobar
    return {
        foobar: foo
    }
});

他のどこかでモジュールを使用できます:

require(["package/myModule"], function(myModule) {
    myModule.foobar();
});

背景:

実際、CommonJSはAPI宣言以上のものであり、その一部しか扱っていません。AMDはCommonJSリストのモジュール形式のドラフト仕様として開始しましたが、完全な合意には至らず、形式のさらなる開発はamdjsグループに移行しました。CommonJSがより広範な懸念をカバーしようとすること、および同期の性質を考えるとサーバー側の開発により適していること、および非同期の性質とDojoのモジュール宣言の実装にルーツがあるという事実。

出典:


1
説明ではなくコードを見ると役立ちます!:) AMD compliant実際にはRequireJSですよね?
Asim KT

何か不足していますか、それともタイプミスしたものがありますか?「package / lib」を定義しますが、「package / myModule」が必要です。
RullDawg 2016

私はいつも何かがなぜそれがそうであるかの歴史について少し読んでみたいです!その背景を提供してくれてありがとう!
Andru

@RullDawgいいえ、「package / lib」はここでは定義されていません。ここで使用されるサードパーティの依存関係です。
Robert Siemer

28

引用

AMD

  • ブラウザファーストのアプローチ
  • 非同期動作と簡略化された下位互換性を選択する
  • ファイルI / Oの概念はありません。
  • オブジェクト、関数、コンストラクター、文字列、JSON、その他多くのタイプのモジュールをサポートしています。

CommonJS

  • 1つのサーバーからのアプローチ
  • 同期動作を想定
  • I / O、ファイルシステム、プロミスなどの幅広い問題をカバーします。
  • ラップされていないモジュールをサポートします。ES.next/ Harmony仕様に少し近づき、強制するdefine()ラッパーを解放しますAMD
  • オブジェクトをモジュールとしてのみサポートします。

17

いくつかのファイルにJavaScriptプログラムのモジュラーを整理すると呼び出すことはかなり正常ですchild-modulesからmain js module

JavaScriptはこれを提供していません。ChromeとFFの最新のブラウザーバージョンでは、現在でもそうではありません。

しかし、JavaScriptに別のJavaScriptモジュールを呼び出すためのキーワードはありますか?

答えがノーであるので、この質問は多くの人にとって世界の完全な崩壊であるかもしれません


ES5(2009年にリリース)では、JavaScriptにはimportincluderequireなどのキーワードがありませんでした。

ES6は、インポートキーワード( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import)を提案する(2015年にリリースされた)日を節約しますが、これを実装するブラウザーはありません。

Babel 6.18.0を使用し、ES2015オプションのみでトランスパイルする場合

import myDefault from "my-module";

あなたはrequire再び得るでしょう。

"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

これはrequire、モジュールがNode.jsからロードされることを意味するためです。Node.jsは、システムレベルのファイルの読み取りから、関数のモジュールへのラッピングまで、すべてを処理します。

JavaScriptでは、関数はモジュールを表す唯一のラッパーだからです。

CommonJSとAMDについてよく混乱していますか?

CommonJSとAMDは、JavaScriptの「欠陥」を克服してモジュールをスマートにロードするための2つの異なる手法にすぎません。


3
現在のすべてのブラウザーがサポートしている ため、回答を更新する必要がありますimport
vsync

@vsync、はい、このセグメントをしばらくフォローしていなかったので、お気軽に私の回答を編集してください。
prosti
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.