Javascriptモジュールベース

6235 ワード

すべてのフロントエンドモジュールを1つのdemoで体験

テーマ


メインストリームモジュールモードAMDとCommonJsモジュールフォーマットクライアントモジュールローダES 2015モジュールモジュール接続

なぜモジュールが重要なのですか?


モジュールは何ですか?


モジュールは、特定の機能を持つコードとデータのセットであり、いくつかの実装の詳細をカプセル化し、共通のAPIを暴露し、他のモジュールとの接続を通じて大規模なアプリケーションを構築します.

モジュール化の目的


ハイレベルの抽象
モジュール化は、それぞれの方法ではなく、より高いレベルからあなたの応用を考えることができます.それは、すべての方法の角度から問題を考えることができます.例を挙げると、もし私が都市の建設者であれば、私はどのように都市の中で建築群を配置するかを考えたいと思っています.すべての建物のレンガの問題を考えるのではなく、どのように都市の中で建築群を配置するかを考えたいと思っています.
パッヶージ
モジュールのタスクは、使用者が使用するために明確なAPIを露出し、具体的な実装の詳細を隠すことです.これにより、モジュールを維持する人は、APIが変わらない限り、使用者に影響を与えることなく、コードを再構築したり、アルゴリズムや他の実装を置き換えたりすることができます.
再利用
依存管理のシンプル化
一般的に、各モジュールは、自分の機能に依存する他のモジュールを宣言する必要があります.HTMLページ上の膨大なjsスクリプトの順序を維持する痛みを知っていて、良いモジュールシステムを実現することでこの問題を解決することができます.

Module Patterns in ES 5(ES 5時代のモジュール)


**IIFE:関数式を即時呼び出し**
グローバル変数汚染は悪いことであることはよく知られています.グローバル変数汚染を解決する手段の一つはIIFEである.
IIFEは匿名関数であり、宣言と同時に呼び出される.これはコードの構造にとって一定の利点がある.JavaScriptでは、変数の役割ドメインは関数にとって、IIFEはただの関数なので、コードの実装ロジックをIIFEにカプセル化することができ、他のコードに呼び出されません.また、IIFEは匿名の関数であり、グローバルな役割ドメインで新しい変数を作成することはありません.これにより、IIFEで定義された関数や変数名とサードパーティ製ライブラリの競合を心配する必要はありません.これはJavaScriptでよく発生する問題であり、モジュール化で解決する問題でもあります.
しかし、IIFEは管理に依存する問題を解決することができないため、彼らはまだ最も理想的な解決策ではない.
**露出モジュールモード**
このモードはJavaScript関数の役割ドメインの特性を利用して実現され,関数の役割ドメインはモジュールの実装の詳細をよくカプセル化することができる.
IIFEとは異なり、コード内のモジュールを参照できるようにするには、グローバル変数に新しい値を追加することを意味する名前が必要です.このモードの欠点は,モジュール間の依存管理形式を提供していないことであるが,JavaScript言語によってサポートされている.
このモードには2つの実装がある:単一例モードと構造関数モード.
**単一モード**
var scoreboard=function(){
         var message=' Welcome to the game! ';
         function printMessage(){
                   console.log(message);
         }
         return {
                  showMessage:printMessage
         }
}();

ここではscoreboardが関数のように見えますが、コードの最後にカッコが付いていることに注意して、すぐにこの関数を呼び出すので、scoreboard変数は実際には関数の戻り値に割り当てられているので、showMessage属性を持つオブジェクトであり、このオブジェクトは新しいモジュールであり、scoreboard変数はこのモジュール全体のアプリケーションで唯一のインスタンスです.
コンストラクタモード
 var Scoreboard=function(){
         var message=' Welcome to the game! ';
         function printMessage(){
                   console.log(message);
         }
         return {
                  showMessage:printMessage
         }
};
var myScoreboard=new Scoreboard();
myScoreboard.showMessage();

ここで関数はすぐに呼び出されなくなりますので、構造関数を表す変数の頭文字を大文字にすることをお勧めします.

モジュールフォーマットvsモジュールローダ


モジュールフォーマット


現在主流のモジュールフォーマットはAMD、CommonJS、UMD、Systemである.register、ES2015.ブラウザによるオリジナルのサポート状況により、前の4種類はnon-nativeとすることができ、ES 2015 Sはnativeに属する.
モジュールフォーマットとは、モジュールを定義するための構文です.
モジュールフォーマットはモジュールローダとは独立して存在し、モジュールローダがなければ、これらの構文を実行する方法を知っている人はいません.
モジュールローダは通常JavaScriptのライブラリであり、プロジェクトに含まれています.彼は私たちのコードで使用されているモジュールフォーマット(どの構文を使用しているか)を理解し、この構文で書かれたモジュールをロードして実行する方法を知っています.モジュールフォーマットとモジュールローダの関係はJavaScript言語とブラウザの関係のようです.
**AMD(Asynchronous Module Definition)形式**
主にブラウザ側でロードされるモジュールを定義するために使用されます.その名前が示すように、AMDフォーマットは非同期ロードモジュールをサポートします.
やはり前の例を使います.プレイヤーモジュールが要求されると、モジュールローダはdefineメソッドを呼び出し、defineの2番目のパラメータ関数を実行します.この関数はモジュールAPIのオブジェクトを返します.これは概念的に露出モジュールモードと非常に似ているが,モジュールの依存性を明確にすることができ,より少ないオブジェクトをグローバル変数に露出させることができる.
//player.js
define([],function(){
         var message=' Welcome to the game! ';
         function printMessage(){
                   console.log(message);
         }
         return {
                  showMessage:printMessage
         }
});

CommonJS形式
より一般的なサーバ側のJavaScriptではNodeに多く用いられる.jsの中.NodeにはCommonJS形式をサポートするモジュールローダが内蔵されています.ただし,SystemJSというモジュールローダを用いてブラウザ側のアプリケーションでCommonJsを使用することも可能である.CommonJSとAMDは全体的に非常に似ており、依存を管理し、各モジュールにAPIを定義することができます.AMDとは異なり、CommonJSのモジュールはfunctionに書かれなくなり、可読性が高くなります.
UMD(universal Module Definition)形式
AMDとCommonJsの2つのフォーマットを互換化してみます.ブラウザ側とサーバ側で同じモジュールをロードする場合は、このモジュールフォーマットを使用することを考慮します.サーバ側ではNodeのCommonJSによって解析され、ブラウザ側ではRequireJsのようなローダによって解析されます.
System.register形式
SystemJSモジュールローダ用に設計されています.SystemJSは複数の異なるモジュールフォーマットをロードすることができるので、必ずしもSystemを使用する必要はない.registerが書きます.
ES 2015は、ES 2015モジュールフォーマットと比較して、上記の4つの定義モジュールの構文がJavaScript言語に組み込まれているわけではありません.彼らは言語から独立して存在する.ES 2015のモジュールフォーマットは、ES 2015、最新版のJavaScript言語でサポートされています.しかし、現在のブラウザでは、ES 2015のすべての新しい機能をサポートすることはできません.これには、モジュール構文が含まれています.ES 2015のモジュール構文を使用して符号化するには、あなたが書いたJavaScriptモジュールを、モジュールローダのサポートの下でブラウザ側で実行できるモジュールフォーマットに変換するための翻訳ステップが必要です.
以上の各種類のモジュールフォーマットに対して、対応する異なるモジュールローダがあります.例えばRequireJSは主にAMD形式のモジュールに対応するが、SystemJSのようにAMD、CommonJS、UMD、Systemを同時に解析することができる.registerなどのモジュールフォーマット.

Modules in ES2015


ES 2015モジュールは天然の言語サポートの優位性を持ち、モジュールの「皇室の血統」に属している.
他のモジュールフォーマットと比較して、依存性を管理し、実装の詳細をカプセル化し、明確なAPIを暴露する機能も管理できます.異なる点は、モジュールローダのサポートは必要ありませんが、現在のブラウザではES 2015のモジュール特性をサポートできないため、使用時に翻訳のプロセスが必要です.モジュールをAMD、CommonJSまたは他のモジュールフォーマットに置き換えてから、ローダで解析する必要があります.
ES 2015は、他のモジュールフォーマットよりもモジュールの導入とエクスポートにおいて柔軟性が高い.
インポート
  • は、インポート依存モジュール
  • をサポートする.
  • はモジュール全体の導入をサポートする、モジュールの一部
  • を導入することもできる.
  • は、モジュールの別名
  • の作成をサポートします.
    エクスポート
  • は、露出モジュールAPI
  • をサポートする
  • は、宣言時にエクスポートすることをサポートし、リスト
  • を一度にエクスポートすることもできる.
  • は、デフォルトのエクスポート
  • の指定をサポートします.

    Module Bundlers


    Module bundlersはモジュールローダと同じ問題を解決していますが、実行時段階ではなくコンパイル段階(build step)で完了しています.
    bundlerは、モジュールローダと同様に、アプリケーションのモジュール依存チェーンを追跡します.しかし、依存が必要なときにダウンロードするのではなく、依存全体を順番にリンクします.bundlingの後、ブラウザはそんなに多くのjsファイルをダウンロードする必要はありません.これはアプリケーションの起動時間を減らす可能性がありますが、これは100%保証できません.開発者は自分で効果をテストしなければなりません.
    非常に大きなモジュールを1つのファイルにリンクすると、アプリケーションがロードに多くの時間を費やす可能性があります.このシーンでは、モジュールローダを使用するとより適切になる可能性があります.
    Browserify
    BrowserifyはNodeJSのために開発したモジュールをブラウザ側で実行するJavaScriptアプリケーションに適用したい.この点はその名前からわかる(It attempts to Browserify Node.js modules)ので、bundleはCommonJS形式のモジュールです.
    Webpack
  • とBrowserifyが異なるのは、WebpackがAMD、CommonJS、ES 2015形式のモジュールをbundleできることです.
  • code splitの機能を提供し、コードをいくつかのbundlesに組織することができ、ダウンロード時により良い最適化効果を得ることができます.
  • Webpackは、bundle CSS、Image、およびその他の静的リソースにも使用できます.
  • loaderを使用するとbundleの前に各種ファイルを前処理できます.

  • ここでは、上述各種類のフロントエンドモジュールフォーマットを用いて、同一のdemoを実現する.興味のある人は見てもいいですよ.https://github.com/qinghaitvxq/Javascript-Module-Fundamentals