JavaScript は、世界で最も頻繁に使用されているプログラミング言語の 1 つであり、Web 世界の共通言語であり、すべてのブラウザーで使用されています。 JavaScript の誕生は Netscape の時代にまで遡ります。その中核となるコンテンツは、当時のマイクロソフトと競争し、激しいブラウザ戦争に参加するために急遽開発されました。時期尚早にリリースされたため、必然的にあまり良くない機能がいくつか生じました。
開発期間が短いにもかかわらず、JavaScript には依然として多くの強力な機能がありますが、各スクリプトがグローバル名前空間を共有する点が異なります。
Web ページが JavaScript コードを読み込むと、そのコードはグローバル名前空間に挿入され、読み込まれた他のすべてのスクリプトと同じアドレス空間を共有します。これにより、多くのセキュリティ上の問題、競合、およびいくつかの一般的な問題が発生します。追跡も解決も困難です。
しかし、ありがたいことに、Node はサーバーサイド JavaScript の仕様をいくつか設定し、CommonJS モジュール標準も実装しました。この標準では、各モジュールが独自のコンテキストを持ち、他のモジュールとは区別されます。これは、グローバル スコープなどというものは存在せず、モジュールは相互に干渉しないため、モジュールがグローバル スコープを汚染しないことを意味します。
この章では、いくつかの異なるモジュールとそれらのロード方法について学びます。
コードを一連の明確に定義されたモジュールに分割すると、アプリケーションを制御するのに役立ちます。以下では、独自のモジュールを作成して使用する方法を学びます。
Node がモジュールをロードする方法を学習します
Node では、ファイル パスまたはモジュール名を通じてモジュールを参照できます。非コア モジュールが名前で参照される場合、Node は最終的にモジュール名を対応するモジュール ファイル パスにマップします。コア機能を含むコア モジュールは、ノードの起動時にプリロードされます。
非コア モジュールには、NPM (ノード パッケージ マネージャー) を使用してインストールされたサードパーティ モジュールと、自分または同僚によって作成されたローカル モジュールが含まれます。
現在のスクリプトによってインポートされた各モジュールは、一連のパブリック API をプログラマに公開します。モジュールを使用する前に、次のように require 関数を使用してモジュールをインポートする必要があります。
エクスポートモジュール
CommonJS モジュール システムは、Node.js 内のファイル間でオブジェクトと関数を共有する唯一の方法です。非常に複雑なプログラムの場合は、いくつかのクラス、オブジェクト、または関数を、明確に定義された一連の再利用可能なモジュールに再構築する必要があります。モジュールのユーザーに対して、モジュールは指定したコードのみを公開します。次の例では、Node のファイルとモジュールの間に 1 対 1 の対応があることがわかります。Circle コンストラクターのみをエクスポートする、circle.js というファイルを作成しました。
return Math.pow(r, 2);
}
関数エリア() {
return Math.PI * r_squared();
}
return {エリア: エリア};
}
module.exports = Circle;
一部の複雑なオブジェクトをエクスポートすることもできます。 module.exports は空のオブジェクトとして初期化され、外部に公開したいコンテンツを module.exports オブジェクトの属性としてエクスポートできます。たとえば、一連の関数を公開するモジュールを設計するとします。
console.log('A');
}
関数 printB() {
console.log('B');
}
関数 printC() {
console.log('C');
}
module.exports.printA = printA;
module.exports.printB = printB;
module.exports.pi = Math.PI;
このモジュールは 2 つの関数 (printA と printB) と数値 (pi) をエクスポートします。呼び出しコードは次のようになります:
myModule2.printA() // ->A
myModule2.printB() // ->B
console.log(myModule2.pi) // -> 3.141592653589793
ロードモジュール
前に述べたように、require 関数を使用してモジュールをロードできます。Node にはグローバル名前空間の概念がないため、コード内での require の呼び出しがグローバル名前空間に影響を与えることを心配する必要はありません。モジュールが存在し、構文エラーや初期化エラーがない場合、require 関数はモジュール オブジェクトを返し、このオブジェクトを任意のローカル変数に割り当てることができます。
モジュールにはいくつかの種類があり、コア モジュール、ローカル モジュール、NPM を通じてインストールされるサードパーティ モジュールに大別できます。モジュールの種類に応じて、モジュールを参照する方法がいくつかあります。これらの知識を。
コアモジュールをロード
ノードには、コア モジュールと呼ばれる、バイナリ ファイルにコンパイルされるモジュールがいくつかあります。これらはパスを通じて参照することはできず、モジュール名のみを参照します。コア モジュールのロード優先度が最も高くなります。同じ名前のサードパーティ モジュールが存在する場合でも、コア モジュールが最初にロードされます。
たとえば、http コア モジュールをロードして使用したい場合は、次のようにすることができます:
これは、Node API ドキュメントで定義されている htpp モジュール API を含む http モジュール オブジェクトを返します。
ロードファイルモジュール
絶対パスを使用してファイル システムからモジュールをロードすることもできます:
var myModule2 = require('./lib/my_module_2');
上記のコードに注意してください。ファイル名の拡張子を省略できます。Node がファイルを見つけられない場合は、ファイル名の後に js 接尾辞を追加して再検索を試みます (翻訳者注: 実際には、 js以外にもjsonやnodeも検索します。詳しくは公式サイトのドキュメントを参照してください)そのため、カレントディレクトリにmy_module.jsというファイルがある場合、読み込み方法は以下の2つになります。 :
var myModule = require('./my_module.js');
ロードディレクトリモジュール
ディレクトリへのパスを使用してモジュールをロードすることもできます:
ノードは、このディレクトリがモジュール パッケージであると想定し、このディレクトリでパッケージ定義ファイル package.json を検索しようとします。
見つからない場合、Node はパッケージのエントリ ポイントが Index.js ファイルであると想定します (翻訳者注: Index.js に加えて、index.node も検索します。.node ファイルはバイナリです) Node の拡張パッケージ。詳細については公式ドキュメントを参照してください)。上記のコードを例として、Node は ./myModuleDir/index.js ファイルを見つけようとします。
逆に、package.json ファイルが見つかった場合、Node はそれを解析し、パッケージ定義内の main 属性を探し、main 属性の値をエントリ ポイントの相対パスとして使用します。 。この例では、package.json が次のように定義されているとします:
"名前" : "myModule",
"メイン" : "./lib/myModule.js"
}
ノードは ./myModuleDir/lib/myModule.js ファイルをロードしようとします
node_modules ディレクトリからロード
require 関数のパラメータが相対パスまたはコア モジュール名ではない場合、Node は現在のディレクトリの node_modules サブディレクトリ内を検索します。たとえば、次のコードでは、Node はファイルを見つけようとします。 node_modules/myModule.js:
この機能を使用して、node_modules ディレクトリのコンテンツまたはモジュールを管理できますが、モジュール管理タスクを NPM に任せることをお勧めします (第 1 章を参照)。ローカルの node_modules ディレクトリは、NPM がモジュールをインストールするデフォルトの場所です。このデザインノードとNPMは相互にリンクされています。通常、開発者はこの機能についてあまり気にする必要はありません。NPM を使用してパッケージをインストール、更新、削除するだけで、node_modules ディレクトリが維持されます
キャッシュモジュール
モジュールは、最初に読み込みが成功した後にキャッシュされます。つまり、モジュール名が同じファイル パスに解決される場合、require('myModule') を呼び出すたびにまったく同じモジュールが返されます。
たとえば、my_module.js というモジュールがあり、これには次のコンテンツが含まれています:
module.exports = function() {
console.log('こんにちは!');
};
console.log('my_module が初期化されました。');
次に、次のコードを使用してこのモジュールをロードします:
次の出力が生成されます:
my_module が初期化されました
2 回インポートすると:
var myModuleInstance2 = require('./my_module');
出力は次のとおりです:
my_module が初期化されました
言い換えると、モジュールの初期化コードは 1 回だけ実行されます。独自のモジュールを構築するとき、モジュールの初期化コードに副作用を引き起こす可能性のあるコードが含まれている場合は、この機能に特に注意してください。
概要
Node は JavaScript のデフォルトのグローバル スコープをキャンセルし、CommonJS モジュール システムを採用することで、コードをより適切に整理し、多くのセキュリティ上の問題やバグを回避できます。 require 関数を使用して、コア モジュール、サードパーティ モジュールをロードしたり、ファイルやディレクトリから独自のモジュールをロードしたりできます
相対パスまたは絶対パスを使用して非コア モジュールをロードすることもできます。モジュールを node_modules ディレクトリに配置する場合、または NPM でインストールされたモジュールの場合は、モジュール名を直接使用してロードすることもできます。
翻訳者注:
読者には、公式ドキュメントのモジュールの章を読むことをお勧めします。個人的には、このドキュメントの方が著者よりも明確でわかりやすいと感じます。また、Node モジュールのロードを理解するのに非常に役立ちます。その例を引用してみましょう:
1. X がコアモジュールの場合、
a. コアモジュールをロードして返します
b. 終了
2. X が './' または '/' または '../' で始まる場合
a. LOAD_AS_FILE(Y X)
b. LOAD_AS_DIRECTORY(Y X)
3. LOAD_NODE_MODULES(X, ディレクトリ名(Y))
4. 例外をスローします:「見つかりません」
LOAD_AS_FILE(X)
1. X がファイルの場合、X を JavaScript スクリプトとしてロードし、
のロード後に終了します。2. X.js がファイルの場合、X.js を JavaScript スクリプトとしてロードし、ロード後に終了します
3. X.node がファイルの場合、X.node を Node バイナリ プラグインとしてロードし、ロードが完了したら終了します
LOAD_AS_DIRECTORY(X)
1. X/package.json ファイルが存在する場合、
a. X/package.json を解析し、「main」フィールドを見つけます。
b. 別の M = X (メインフィールドの値)
c. LOAD_AS_FILE(M)
2. X/index.js ファイルが存在する場合は、X/index.js を JavaScript スクリプトとして読み込み、読み込み後に終了します
3. X/index.node ファイルが存在する場合は、X/index.node を Node バイナリ プラグインとしてロードし、ロードが完了したら終了します
LOAD_NODE_MODULES(X, START)
1. DIRS=NODE_MODULES_PATHS(START)
2. DIRS の下の各ディレクトリ DIR に対して次の操作を実行します。
a. LOAD_AS_FILE(DIR/X)b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. 別の PARTS = パス分割(START)
2. 別の ROOT = PARTS の「node_modules」の最初のインスタンスのインデックス、または 0
3.I = パーツの数 - 1
4. 別の DIRS = []
5. ルート中、
a. PARTS[I] = "node_modules" の場合は、後続の操作を続行します。それ以外の場合は、次回ループします
c. DIR = パス結合(PARTS[0 .. I] "node_modules")
b. DIRS = DIRS DIR
c. 別の I = I - 1
6. DIRS に戻ります