モジュラーフロントエンド - 徹底的AMD、CMD、ESMとCommonJSを知ってもらいます

私たちは何過度に複雑な開発シナリオが存在しないためNodeJS前に、フロントエンドは、モジュール式ではないことを知っている、モジュール式のバックエンドにのみ存在します。NodeJS出産後、それはCommonJSのモジュール仕様を使用しています。それ以来、モジュラーjsが急速な発展を開始しました。

モジュラー開発アプローチは、簡単なコードを管理するために、コードの再利用率を提供することができます。典型的には、ファイルがモジュールである、独自の範囲、外部に露出のみ特定の変数と関数を有していますJsの人気のモジュラー仕様はCommonJS、AMD、CMDおよびES6のためのモジュラーシステムを持っています。ここでは、一つ一つを導入し始めます。

CommonJS

NodeJSはCommonJSメイン実務仕様です、それは4つの重要な環境変数は、モジュラー実現のためのサポートを提供していますmoduleexportsrequireglobal実際の使用、module.exportsインターフェースモジュール現在の外部出力の定義(直接使用することは推奨しないexportsと)、requireロードモジュール。

// 定义模块math.js
var basicNum = 0;
function add(a, b) {
  return a + b;
}
module.exports = { //在这里写上需要向外暴露的函数、变量
  add: add,
  basicNum: basicNum
}

/** 必须加./路径,不加的话只会去node_modules文件找 **/
// 引用自定义的模块时,参数包含路径,可省略.js
var math = require('./math');
math.add(2, 5);

// 引用核心模块时,不需要带路径
var http = require('http');
http.createService(...).listen(3000);

同期してモジュールをロードCommonJS。これは問題ありませんので、サービス側では、モジュールファイルは、非常に高速で読み、ローカルディスクに保存されます。しかし、ブラウザがネットワーク上の理由に限定され、より合理的な解決策は、非同期ロードを使用することです。

exportsそして、module.exportの違い:

exports:自体の変数(オブジェクト)の観点から、それがである、基準モジュールでない{}とポイント参照module.exports({})ブロック。のみを使用し.、構文露光変数外。

module.exportsmoduleメモリへのポイントは、という変数でexportsあるmoduleメモリに保存され、その後、属性exportsに属性ポイント{}モジュール。あなたはどちらかを使用することができ.ます。また、使用することができ、構文を=直接割り当てを。

AMD和require.js

AMDの仕様が使用する非同期ロード・モジュールを、モジュールは、それが文の背中の動作には影響を与えませんロードされます。この文は、すべての依存モジュールは、コールバック関数で定義されている、ロード完了後まで待って、コールバック関数が実行されます。ここでモジュラーrequire.js AMD仕様に実装されていますとrequire.config()経路指定、参照definde()定義モジュール、require()ロードモジュール。

まず、我々はrequire.jsファイルとファイルエントリmain.js.を導入する必要があります main.jsを設定require.config()し、プロジェクトで使用される基本的なモジュールを提供します。

/** 网页中引入require.js及main.js **/
<script src="js/require.js" data-main="js/main"></script>

/** main.js 入口文件/主模块 **/
// 首先用config()指定各模块路径和引用名
require.config({
  baseUrl: "js/lib",
  paths: {
    "jquery": "jquery.min",  //实际路径为js/lib/jquery.min.js
    "underscore": "underscore.min",
  }
});
// 执行基本操作
require(["jquery","underscore"],function($,_){
  // some code here
});

リファレンス・モジュールは、我々はモジュール名を置く[]ようreqiure()最初のパラメータ、我々はモジュール自体も、他のモジュールに依存している定義した場合、それらを配置する必要がある[]として、define()最初のパラメータ。

// 定义math.js模块
define(function () {
    var basicNum = 0;
    var add = function (x, y) {
        return x + y;
    };
    return {
        add: add,
        basicNum :basicNum
    };
});

// 定义一个依赖underscore.js的模块
define(['underscore'],function(_){
  var classify = function(list){
    _.countBy(list,function(num){
      return num > 30 ? 'old' : 'young';
    })
  };
  return {
    classify :classify
  };
})

// 引用模块,将模块放在[]内
require(['jquery', 'math'],function($, math){
  var sum = math.add(10,20);
  $("#sum").html(sum);
});

CMDとsea.js

AMDの実装は、最初の時間、実行するモジュールのコードにロードされたモジュールに依存して述べrequire.js。

define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) { 
    // 等于在最前面声明并初始化了要用到的所有模块
    if (false) {
      // 即便没用到某个模块 b,但 b 还是提前执行了。**这就CMD要优化的地方**
      b.foo()
    } 
});

CMDは、別のjsのモジュラーアプローチであることがことを除いて、AMDと非常によく似ています:AMDは、事前に実行され、前面に依存尊敬、CMDは近く、遅延実行を依存している尊敬しましたこの仕様は、実際にsea.jsプロモーションプロセスで製造されます。

/** AMD写法 **/
define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) { 
     // 等于在最前面声明并初始化了要用到的所有模块
    a.doSomething();
    if (false) {
        // 即便没用到某个模块 b,但 b 还是提前执行了
        b.doSomething()
    } 
});

/** CMD写法 **/
define(function(require, exports, module) {
    var a = require('./a'); //在需要时申明
    a.doSomething();
    if (false) {
        var b = require('./b');
        b.doSomething();
    }
});

/** sea.js **/
// 定义模块 math.js
define(function(require, exports, module) {
    var $ = require('jquery.js');
    var add = function(a,b){
        return a+b;
    }
    exports.add = add;
});

// 加载模块
seajs.use(['math.js'], function(math){
    var sum = math.add(1+2);
});

ES6モジュール

言語標準のレベルにES6は、機能モジュールを実現し、ブラウザとサーバモジュールソリューション多彩なように設計された非常に簡単に、実現しています。その主な機能モジュールは、次の2つのコマンドで構成されていますexportimportexportコマンドは、モジュールの外部インタフェースを指定するために使用されるimport他のモジュールによって提供されるコマンド入力機能。

/** 定义模块 math.js **/
var basicNum = 0;
var add = function (a, b) {
    return a + b;
};
export { basicNum, add };

/** 引用模块 **/
import { basicNum, add } from './math';
function test(ele) {
    ele.textContent = add(99 + basicNum);
}

図示のように、使用するimportコマンドを、ユーザーは、変数名や関数名をロードするために知っておく必要があります。実際にはES6も提供しexport default、デフォルトの出力モジュールを指定するコマンドを、対応するimport文は、中括弧を使用する必要はありません。また、ADMの文言により近い引用しました。

/** export default **/
//定义输出
export default { basicNum, add };

//引入
import math from './math';
function test(ele) {
    ele.textContent = math.add(99 + math.basicNum);
}

ES6モジュールはオブジェクトではなく、importコマンドではなく、コードの実行をロードする、モジュールコードの導入でコンパイルするJavaScriptエンジンの静的解析、あろう、それは負荷条件に可能ではありません。正確にはこのために、それは静的な解析が可能になります。

ES6モジュールの機能:

  • strictモード:ES6モジュールが自動的にstrictモードを使用
  • import読み取り専用プロパティ:importプロパティは読み取り専用され、割り当てることができない、同様のconst特性
  • export/importアップグレード:import/exportトップモジュールでなければなりません、あなたはスコープにすることはできません。第二に、モジュール内のためにimport/exportコンパイル段階で行われているモジュールの上部に引き上げられます

違いES6モジュールとモジュールCommonJS

1. CommonJSモジュール出力値のコピーである、ES6モジュールの出力が基準値であります
  • CommonJSモジュール出力はコピーされた値は、出力値と、言うことである、モジュール内の変更は、この値に影響を与えることはできません
  • 操作機構とCommonJS ES6モジュールは同じではありません。静的解析のためのスクリプト、経験モジュールのロードコマンドはJSエンジンimport、それは読み取り専用の参照を生成します。スクリプトが実際に実行されるまで待ってから、モジュールに、この読み取り専用の基準に基づいて値を内部に装填されます。換言すれば、ES6ためのimportビットUnixシステム「シンボリックリンク」のような、元の値が変更され、import変数ローディングの値が続きます。したがって、ES6モジュールに対して、モジュール内のモジュール内の変数のバインディング動的基準値であり、キャッシュされていません。
ランタイムモジュールがロードされている2 CommonJSは、ES6出力インタフェースモジュールは、コンパイル時です
  • 場合ローディング動作:CommonJSオブジェクトモジュールであり、入力モジュールは、オブジェクトを生成するために、全体をロードするとき、オブジェクトは、上記方法から読み出され、すなわち、この荷重は、「負荷運転」と呼ばれます。
  • ロードコンパイル時間:ES6モジュールはオブジェクトではなく、によってexportコードコマンド明示的出力、指定されたimport静的コマンドの形式です。すなわち、importむしろ全体のモジュールをロードするよりも、指定された出力値にロードすることができ、この負荷は、「コンパイル時のロード」と呼ばれます。内部モジュールが変更を参照し、外部に反応します。

CommonJSオブジェクト(すなわちの負荷module.exports特性)、オブジェクトはスクリプトの生成を実行完了します。ES6モジュールではなく、オブジェクト、それだけ静的外部インターフェース定義だ、コードが静的解決フェーズで生成されます。

騒ぎ、コードで直接見て:

例CommonJSを最初の出力のコピーを参照してください。

// a.js
let a = 1;
let b = { num: 1 }
setTimeout(() => {
    a = 2;
    b = { num: 2 };
}, 200);
module.exports = {
    a,
    b,
};

// main.js
// node main.js
let {a, b} = require('./a');
console.log(a);  // 1
console.log(b);  // { num: 1 }
setTimeout(() => {
    console.log(a);  // 1
    console.log(b);  // { num: 1 }
}, 500);

出力コピーいわゆる、またはあなたが(知らないこの見ることができますあまりにもNodeJS WebPACKのはCommonJSを達成知っていれば記事を)、あなたが知っている:exportsオブジェクトは、一意のモジュールの内側と外側、あるコンテンツCommonJS出力、関連付けられているexportsオブジェクトの属性の終了、モジュールの実行を、属性が決定されます

例ES6モジュールルック出力:

// a.mjs
let a = 1;
let b = { num: 1 }
setTimeout(() => {
    a = 2;
    b = { num: 2 };
}, 200);
export {
    a,
    b,
};

// main.mjs
// node --experimental-modules main.mjs
import {a, b} from './a';
console.log(a);  // 1
console.log(b);  // { num: 1 }
setTimeout(() => {
    console.log(a);  // 2
    console.log(b);  // { num: 2 }
}, 500);

出力およびES6モジュールCommonJS出力値との差は、上記で引用され、反応はES6モジュール仕様で外側になり、内部モジュールが参照変更。

概要

  1. AMD / CMD / CommonJs JSモジュラー開発は、対応する実装が指定されているrequire.js / sea.js / Node.jsの

  2. CommonJsは、主にサーバー用に、AMD / CMD / ESモジュールは、AMD / CMDで混乱、ブラウザを目的としました。(ちなみに、モジュールを必要とすることの終わりは何か?一般的なサーバー側の同期ロードファイル、のためのサーバとブラウザ間の差のために、サーバが停止し、それが再びロードして実行するのを待ちます。ここならばJavaなどの他のバックエンドの言語があります。ブラウザ側は効率性を確保するために、我々は、並列ロードモジュールファイルは良好である必要があります事前に前処理を必要とする非同期読み込みが必要です。)

  3. AMD / CMD差彼らは並列負荷のjsファイルですが、それでも異なるが、AMDは、同時並列ロードのjsファイルにあらかじめロードされているが、また、モジュールの実装を解析する(また、モジュールをロードする前にそうする必要があるので、このモジュールは、モジュールの必要性に依存してロードする)、およびそれが並列ロードのjsファイルを開始しますが、CMDは、遅延ロードされますが、実行されませんが、必要なときにのみ実行します。

  4. AMD / CMDの長所と短所。もう一つの利点は欠点である、ブラウジングを制御することができます。
    AMD長所:あなたは、同時に複数のファイルを解析することができるように高速ローディングは、特に、並列解像度ので、複数の大きなファイルに遭遇します。
    AMDの欠点:パラレル・ロード、非同期処理、ロードシーケンスは必ずしもないが、それもプログラム埋葬ピットのために、いくつかの混乱を引き起こす可能性があります。

    CMD利点:使用中、従って、JSファイルの各々の実行の順序は、コードに反映されている場合解像度のみJSファイル場合に行われるので、制御可能です。

    CMD短所:実行待ちの時間が重畳されます。各ファイルの実行が(シリアル実行)同期して実行するので、時間が特により大きなファイルでは、時間のすべてのファイルの解析と実行されているので、この欠点は、特に顕著です。PS(:再読み込み、この記事で、書いてここに見つけるには非常に正確かつ精密な用語ではありません、それは使用時に実行することであるとして、JSは、シングルスレッドで、すべてのJSファイルの実行時間は、AMDとCMD CMDを重畳し、同じことができないです。自由時間の使用は、しかし、AMDは、多くの場合、いくつかの自由時間を活用することができ、良いの実装にロードされたファイルである。そう、AMDよりもメリットCMDは、すべての後に、まだ非常に明白である、AMDは必ずしもJSエンジンのアイドル時間をロードするための良い時間ではありません!)

  5. CommonJS差とESモジュール:CommonJSモジュールの出力は、ES6モジュールの出力が基準値値のコピーであります

  6. どのように使用するには?CommonJsワード、NodeJSがライン上で使用するノードので、その実装であるため、彼らは他のパッケージを導入していません。AMDが通過される<script>ラベル導入require.js、CMDはsea.jsを導入し、

おすすめ

転載: www.cnblogs.com/chenwenhao/p/12153332.html