ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js_node.js の require の動作原理の簡単な分析

Node.js_node.js の require の動作原理の簡単な分析

WBOY
WBOYオリジナル
2016-05-16 16:43:121362ブラウズ

ほぼすべての Node.js 開発者は、require() 関数が何をするのかを説明できますが、それがどのように機能するかを実際に知っている人はどれだけいるでしょうか?私たちはライブラリやモジュールをロードするために毎日これを使用していますが、その動作は私たちにとって謎です。

好奇心から、私はノードのコアコードを調べて、内部で何が起こっているのかを調べました。しかし、これは単一の関数ではありません。node のモジュール システムで module.js を見つけました。このファイルには、各ファイルのロード、コンパイル、キャッシュを制御する、驚くほど強力だが比較的馴染みのないコア モジュールが含まれています。 「require()」、その出現は氷山の一角にすぎません。

モジュール.js

コードをコピーします コードは次のとおりです:

関数モジュール(id, 親) {
this.id = id;
this.exports = {};
This.parent = 親;
// ...

Module.js は Node.js 内で主に 2 つの役割を果たします。まず、すべての Node.js モジュールの基盤を提供します。各ファイルは、ファイルの実行後も存続する基本モジュールの新しいインスタンスです。そのため、module.exports に属性を付加し、必要に応じて属性を返すことができます。

このモジュールの 2 番目の主要なタスクは、ノードのモジュール読み込みメカニズムを処理することです。私たちが使用する独立した操作「require」関数は、実際には module.require の抽象概念であり、それ自体は Module._load 関数の単純なカプセル化にすぎません。このロード メソッドは各ファイルの実際のロードを処理し、そこから作業を開始します。

モジュール._load

コードをコピーします コードは次のとおりです:

Module._load = function(request,parent,isMain) {
// 1. キャッシュされたモジュールの Module._cache を確認します。 // 2. キャッシュが空の場合は、新しいモジュール インスタンスを作成します。
// 3. キャッシュに保存します。
// 4. 指定されたファイル名を使用して module.load() を呼び出します。
// ファイルの内容を読み取った後に module.compile() を呼び出します。
// 5. ファイルのロード/解析中にエラーが発生した場合、
// 不良モジュールをキャッシュから削除します
// 6. module.exports
を返す };
Module._load は、新しいモジュールのロードとモジュール キャッシュの管理を担当します。ロードされた各モジュールをキャッシュすると、冗長なファイル読み取りの数が減り、アプリケーションの速度が大幅に向上します。さらに、共有モジュール インスタンスにより、モジュールのシングルトン機能をプロジェクトの状態に維持できます。

モジュールがキャッシュに存在しない場合、Module._load はそのファイルの新しいベース モジュールを作成します。次に、新しいファイルの内容を module._compile に送信する前に読み取るようにモジュールに指示します。 [1]

上記のステップ #6 に気付いた場合は、module.exports がユーザーに返されていることがわかります。これが、使用するパブリック インターフェイスを定義するときに、exports と module.exports を使用する理由です。これは、次に Module._load が必要なコンテンツを返すためです。これ以上の機能がないことに驚いていますが、あれば便利です。

module._compile

コードをコピーします コードは次のとおりです:
Module.prototype._compile = function(コンテンツ, ファイル名) {
// 1. module.require.
を呼び出すスタンドアロンの require 関数を作成します。 // 2. 他のヘルパー メソッドを require にアタッチします。
// 3. require を提供する関数で JS コードをラップします
// モジュールなどの変数をモジュール スコープに対してローカルに配置します。
// 4. その関数を実行します
};

・ここで本当の魔法が起こります。まず、このモジュール用に特別なスタンドアロンの require 関数が作成されます。これは私たち全員が必要とする、よく知られた機能です。関数自体は Module.require の単なるパッケージであり、あまり知られていない使いやすい補助メソッドも含まれています。

・require(): 外部モジュールをロードします
· require.resolve(): モジュール名を絶対パスに解決します
· require.main:メインモジュール
· require.cache: キャッシュされたすべてのモジュール
· ·require.extensions: 拡張子に応じた有効なファイル タイプごとに利用可能なコンパイル方法

require の準備が完了すると、ロードされたソース コード全体が、require、module、exports、およびその他すべての公開変数をパラメーターとして受け入れることができる新しい関数にカプセル化されます。これは、Node.js 環境との競合を防ぐためにモジュールをカプセル化するためだけに作成された関数です。

コードをコピー コードは次のとおりです:

(関数 (エクスポート、要求、モジュール、__filename、__dirname) {
// コードがここに挿入されました!
});

Module._compile メソッドは同期的に実行されるため、Module._load への呼び出しは、このコードの終わりまで待機することしかできず、ユーザーに module.exprts を返します。

結論

これで、require のコード全体を理解し、それがどのように機能するかについて暫定的に理解しました。

これをすべて実行した場合は、最後のシークレットである require('module') を使用する準備ができています。そうです、モジュール システム自体はモジュール システムを通じてロードできます。インセプション。奇妙に聞こえるかもしれませんが、これにより、Node.js コアを深く掘り下げることなく、ユーザー空間がモジュール読み込みシステムと対話できるようになります。一般的なモジュールはこのように構築されます。 [2]

さらに詳しく知りたい場合は、module.js のソース コードを自分で調べてください。しばらく頭が痛くなるようなことがたくさんあります。最初の方は、「NODE_MODULE_CONTEXTS」とは何か、そしてそれが追加された理由、そしてそれを追加した人はボーナスポイントを獲得できるのか教えてください:)

[1] module._compile メソッドは、JavaScript ファイルを実行するためにのみ使用されます。 JSON ファイルは JSON.parse() で解析して返す必要があります

[2] ただし、どちらのモジュールも Module._resolveLookupPaths や Module._findPath などのプライベート モジュール メソッドに基づいて構築されています。あまり良くないと思うかもしれません...

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。