nodeJs学習ノート-Nodeのモジュール実現

5389 ワード

nodeJs学習ノート-Nodeのモジュール実現
Common JS仕様
Common JS モジュールの定義は非常に簡単で、主にモジュール参照、モジュール定義、モジュール識別の3つの部分に分けられます.
モジュール参照
var math=require('math')
モジュール定義
モジュールにおいて、コンテキストは外部モジュールを導入するためのrequire()方法を提供し、導入された機能に対応して、コンテキストは現在のモジュールを導出するための方法と変数を提供し、それは唯一のエクスポートである.モジュールの中には、モジュール自体を代表するmoduleオブジェクトも存在し、expirtsはmoduleの属性であり、Nodeでは、一つのファイルはモジュールであり、メソッドをexportsオブジェクトにマウントすることで、属性として定義されて導き出すことができる.
//    
// hello.js
function Hello(){
  var name;
  this.setName = function(thyName){
    name = thyName
  }
  this.sayHello = function(){
    console.log('hello ' + name);
  }
}

exports.Hello = Hello;

// main.js

var Hello = require('./hello.js').Hello;

//    
// hello.js
function Hello(){
  var name;
  this.setName = function(thyName){
    name = thyName
  }
  this.sayHello = function(){
    console.log('hello ' + name);
  }
}
module.exports = Hello;

// main.js

var Hello = require('./hello.js')
PS:exportに直接値を割り当てることによってmodule、exportsに対して値を割り当てることができません.exportsは実際にはmodule.exportsと同じ対象の変数だけを指しています.それ自体はモジュール実行終了後にリリースされますが、moduleはできません.したがって、module.exportを指定することによってのみこのインターフェースにアクセスできます.
モジュールの識別
モジュール識別は実際にrequire()メソッドに渡されるパラメータであり、彼は必ず小さいラクダのピークに合う名前の文字列でなければなりません.これはファイルの拡張子がなくてもいいです.
Nodeのモジュール実現
Nodeは実現する上で完全に規範によって実現するのではなくて、モジュールの規範に対して一定の取捨選択を行って、同時に少しの自身の必要とする特性をも増加しました.
Nodeにモジュールを導入するには、3つのステップが必要です.
  • パス解析
  • ファイル位置決め
  • コンパイル実行
  • Nodeでは、モジュールは二つの種類に分けられます.一つはNodeが提供するモジュールで、コアモジュールといいます.一つはユーザーが自分で作成したモジュールで、ファイルモジュールといいます.
    コアモジュールについて:コアモジュール部分はNodeソースコードのコンパイル中にバイナリ実行ファイルをコンパイルしました.Nodeプロセスが起動すると、コアモジュールの一部が直接メモリにロードされますので、この部分のコアモジュールが導入される時、ファイルの位置付けとコンパイルはこの二つのステップを省略して、パス分析で優先的に判断できます.
    ファイルモジュールについて:ファイルモジュールは、実行中に動的にロードされ、完全なパス、ファイルの位置付け、コンパイル実行プロセスが必要で、速度も最も遅いです.
    モジュールのロードプロセス
    キャッシュから優先的に読み込む
    Nodeは導入したモジュールに対してキャッシュを行い、二次導入時のオーバーヘッドを低減します.ブラウザはファイルのみをキャッシュし、Nodeキャッシュはコンパイルと実行後のオブジェクトです.
    コアモジュールであれ、ファイルモジュールであれ、require()方法は同じモジュールの二次ローディングに対してすべてキャッシュ優先方式を採用しており、これは第一優先順位であり、コアモジュールのキャッシュチェックはファイルモジュールのキャッシュチェックより優先的である点が異なる.
    パス解析とファイルの位置付け
    モジュール識別子分析
  • コアモジュール:最速
  • パス形式のファイルモジュール:より速い
  • カスタムモジュール:遅くとも
  • ファイルの位置
  • ファイルの拡張子の分析は.js、.node、.jsonの順に拡張子を補充して、順次試みます.
  •   PS:拡張子をつけて性能問題を防止することを提案します.
  • カタログ分析とパッケージ:まずpackage.jsonファイルを検索します.このファイルが存在しないなら、index.js、index.node、index.json
  • を探します.
    モジュールコンパイル
    Nodeでは、各ファイルモジュールは一つのオブジェクトです.
    コンパイルと実行はファイルモジュールを導入する最後の段階で、特定のファイルを特定した後、Nodeはモジュールオブジェクトを新規作成し、パスに従ってロードしてコンパイルします.異なるファイルの拡張子についても、ロード方法は異なる.
  • .jsファイルは、fsモジュールによって同期してファイルを読み込み、コンパイルして
  • を実行します.
  • .nodeファイルは、c/c++で作成された拡張ファイルを介して、最後にコンパイルされたファイル
  • をdleopen()でロードする.
  • .jsonファイルは、fsモジュールによって同期してファイルを読み込んだ後、JSON.parse()方法を用いて解析し、結果を返します.
  • 他の拡張ファイルは、すべてjsファイルとしてロードされています.
  • PS:コンパイルに成功したモジュールのファイルパスはインデックスとして保存されます.cacheオブジェクトでは,二次導入の性能を向上させる.
    javascriptモジュールのコンパイル
    コンパイルの過程で、Nodeは取得したjavascriptファイルの内容に対してヘッドエンド包装を行いました.頭に追加しました.
    (function(exports,require,module,__filename,__dirname){
      var math = require('math');
      exports.area = function(radius){
        return Math.PI * radius * radius
      }
    });
    このように各モジュールファイル間でドメイン分離が行われています.
    C/C++モジュールのコンパイル
    Nodeはprocess.dleopenを呼び出して方法をロードして実行して、Nodeフレームワークの下で、dleopen()方法はwindowと**nixプラットフォームの下でそれぞれ異なった実現があって、libuv互換層を通してカプセル化します.
    JSONファイルのコンパイル
    Nodeは、fsモジュールを利用して、JSONファイルの内容を同期して読み込んだ後、JSON.parse()方法を呼び出してオブジェクトを取得し、モジュールオブジェクトのexportに値を付けて外部呼出しする.
    Nodeコアモジュール
    Nodeのコアモジュールは二つに分けられています.c/c+作成の+javascript作成の
    その中のc/c+はNodeプロジェクトのsrcディレクトリの下に置いてあります.javascriptが作成したのはlibディレクトリの下に置いてあります.
    javascriptコアモジュールのコンパイルプロセス
      1.c/c+コードに変換する
       NodeはV 8に付属するjs 2 c.pyツールを採用して、すべての内蔵のjavascriptコード(src/node.jsとlib/*.js)をc+の中の配列に変換して、node_を生成します.natives.hヘッダファイル
      このプロセスでは、Javascriptコードは文字列としてnode名前空間に格納され、直接実行できない.Nodeプロセスを起動する時、javascriptコードは直接メモリにロードされます.ロード中に、Javascriptコアモジュールは識別分析を経てメモリに直接的に位置します.これは普通のファイルモジュールよりディスクの中の一箇所の検索が速いです.
      2.javascriptコアコードをコンパイルする
      libディレクトリの下にあるすべてのモジュールファイルも、require、module、exportなどの変数を定義していません.javascriptコアモジュールに入る過程においても、ヘッドパッキングの過程を経て、exportオブジェクトを実行し、エクスポートしました.
      ファイルモジュールとの違いは、ソースを取得する方法(コアモジュールはメモリから直接読み込む)と、キャッシュ実行結果の位置です.
      javascriptコアモジュールの定義は以下の通りです.ソースファイルはprocess.bindingを通じて取り出し、成功したモジュールをコンパイルしてNativeModule._にキャッシュします.cache対象はファイルモジュールがModule._にキャッシュされます.cache対象に
    function NativeModule(id){
      this.filename = id + '.js';
      this.id = id;
      this.exports = {};
      this.loaded = false;  
    }
    NativeModule._source = process.binding('natives');
    NativeModule._cache = {};
    c/c+++コアモジュールのコンパイルプロセス
    私たちはそれらの純c/c++によって編纂された部分を統一して内建モジュールと呼びます.それらは通常ユーザーに直接呼び出されないからです.Nodeの中で、buffer、crypt、evals、fs、osなどのモジュールは全部部分的にc/c+を通じて編纂したのです.
  • 内にモジュールを構築する組織形態
  • 内構築モジュールの導出
  • c/c++拡張モジュール
    少し、話が深すぎて、読めません.後でゆっくりかじりましょう.
    モジュールコールスタック
    少し、話が深すぎて、読めません.後でゆっくりかじりましょう.
    パッケージとNPM
    パッケージ構造
    パッケージは実際にアーカイブファイルです.つまりディレクトリを直接パッケージにします.zipまたはtar.gz形式のファイルをインストールして解凍してディレクトリに戻します.Common JS規格に適合したパッケージカタログは以下のファイルを含むべきです.
  • package.json: パッケージ記述ファイル
  • bin: 実行可能なバイナリファイルを保存するためのディレクトリ
  • lib: javascriptコードを保存するためのディレクトリ
  • doc: ドキュメントを保存するためのディレクトリ
  • test: セルテスト用例を格納するためのコード
  • パッケージ記述ファイルとNPM
    少し、話が深すぎて、読めません.後でゆっくりかじりましょう.
    前後端共通モジュール
    少し、話が深すぎて、読めません.後でゆっくりかじりましょう.