ホームページ >ウェブフロントエンド >jsチュートリアル >seajs_Seajs のモジュール化とロード方法の詳細な調査
使い始めてseajsのソースコードを知りました。以下の質問に対する私の理解は次のとおりです:
1. seajs の require(XXX) メソッドはモジュールの読み込みをどのように実装しますか?
2. プリロードが必要なのはなぜですか?
3. ビルドツールが必要な理由は何ですか?
4. ビルド前とビルド後のコードの違いは何ですか?また、これを行う理由は何ですか?
質問 1: seajs の require(XXX) メソッドはモジュールの読み込みをどのように実装しますか?
コードのロジックはかなり複雑です。ソース コードの理解については、この記事の最後で説明します。
1. seajs.use メソッドのエントリから、使用するモジュールのロードを開始します。
2. 使用されるモジュールは現時点では MOD キャッシュに存在してはなりません。 seajs は新しい MOD を作成し、それに初期ステータスを与えます。
3. mod.loadメソッドを実行します
4. 一連のロジックの後、seajs.request メソッドに移動し、モジュール ファイルをリクエストします。モジュールがロードされた後、define メソッドが実行されます。
5.defineメソッドはモジュールの依存モジュールを解析・抽出して保存します。ファクトリはキャッシュされますが、実行されません。
6. モジュールの依存モジュールが再度ロードされます。依存モジュールがまだある場合は、ロードが続行されます。すべての依存モジュールがロードされるまで。
7. すべてのモジュールがロードされたら、use メソッドのコールバックを実行します。
8. モジュールの内部ロジックはコールバックから実行されます。 require メソッドはこのプロセス中にのみ実行されます。
質問 2: プリロードが必要なのはなぜですか?
すべての依存モジュールがロードされた後、seajs.use メソッドが実際にコールバックを実行していることがわかります。ビジネス ロジック コードを実行する前に、すべての依存モジュール コードをプリロードする必要があることがわかります。では、なぜ最初にプリロードする必要があるロジックがあるのでしょうか?
答えは、ロジック コード内の他のモジュール メソッドを参照する require メソッドの実行メソッドにあります。
var mod = require(id);
この構文は、モジュールの取得が同期実行プロセスであることを決定します。モジュール コードが以前にプリロードされていない場合は、非同期ロード コールバック メソッドを使用してのみ実装でき、seajs 実行ロジック全体が完全に実行されます。何か他のもの。非同期のため、モジュールの実行順序がわからなくなり、ロジックの制御が難しくなります。
質問 3: ビルド ツールが必要な理由は何ですか?
ビルドする前に、依存する各モジュールが個別にロードされていることがわかります。これにより、過剰なモジュール リクエストが生成され、ページ読み込みのパフォーマンスに悪影響を及ぼします。ビルド ツールは基本的に、結合されたモジュールの読み込みの問題を解決するように設計されています。
質問 4: ビルド前とビルド後のコードの違いは何ですか?また、これを行う理由は何ですか?
ビルド ツールは正確に何をするものですか。本質的にはコードのマージロードの問題を解決するためであると言っていますが、それは単にさまざまなモジュールファイルを 1 つのファイルにマージするだけなのでしょうか?
もちろんそうではありません。テストしてみましょう。複数のモジュール ファイルを 1 つのファイルにマージしただけでは、このファイルは正常に実行できないことがわかります。
その理由はdefineメソッドの実装にあります。
Seajs では、モジュールを定義するときに、define メソッドでファクトリ パラメータのみを渡すことをお勧めします。定義メソッドを振り返ると、ID (モジュールの URL に一時的に相当) が渡されない場合、getCurrentScript() メソッドを使用して現在実行されているモジュール ファイルの URL パスを取得し、このパスがモジュール自体と一緒にキー値として使用されます。ここで重要な点は、seajs 全体内のモジュール キャッシュ メカニズムが、実際には各モジュールの URL をキャッシュ キーとして依存しているということです。 require(id) メソッドは、最終的に URL キー値を介して提供されます。 require(id) メソッドは最終的に URL キー値を使用して、cachedMods 内の対応するモジュールを見つけます。このキー値は繰り返したり、間違えたりすることはできません。そうしないと、モジュール間の対応関係が混乱してしまいます。複数のモジュール ファイル a、b、c がターゲット ファイル x に単純にマージされた場合、getCurrentScript() は x のパスしか取得できず、3 つのモジュールのキー値を区別できず、実行は確実に行われません。間違っている。
したがって、複数のモジュール ファイルをマージしたい場合は、各モジュールの URI を指定する必要があります。つまり、define メソッドは id パラメーターを渡す必要があります。 ID が渡されると、seajs は ID を URL に変換し、それをキャッシュ キーとして使用します。
id と Factory のみが渡された場合、つまり、define(id, Factory) の場合、deps = unknown の場合、define メソッドは parseDependency(factory.toString()) メソッドを実行して、ファクトリ内の依存モジュールを抽出します。次に、モジュール パスを解析し、各モジュールのロジックをオンラインで個別にロードします。この時点では、結合ロードの意味は失われます。
マージロードの場合、define メソッドが正しく実行されるためには、id、deps、factory の 3 つのパラメーターを正しく渡す必要があります。
Seajs のいわゆる CMD モジュール定義メソッドでは、モジュール作成フェーズ中にファクトリという 1 つのパラメータだけを渡すことが全員に推奨されており、他の 2 つのパラメータは後のコード構築フェーズで生成されます。上記は、構築後にこれら 2 つのパラメータが必要な理由を説明しています。
モジュールを定義するときにファクトリのみを渡すことが推奨される理由については、主に手動で渡される id パラメータと deps パラメータは非常にエラーが発生しやすく、保守が不便であるためだと思います。ツールを使用すると効率が向上し、正しいパラメーターを確保できます。
添付: seajs のメイン コード ロジックの理解。
注: ソース コードのバージョンは Sea.js 2.3.0 です
1. まず、define メソッドの機能を見てみましょう
Module.define = function (id、deps、factory)
define メソッドは 3 つのパラメータをサポートしています。このうち、id と deps はオプションです。工場が必要です。コードは次のロジックによって制御されます:
しかし、実際には deps が必要です。seajs は各モジュールがどのモジュールに依存しているかを知っている必要があり、そうでないとロードできないからです。
したがって、ファクトリが関数であり、deps がアクティブに渡されない場合は、parseDependency メソッドを使用してファクトリ内の依存モジュールを分析する必要があります。
parseDependency メソッドが行う主な処理は、正規表現を使用して、関数本体内のすべての require(XXX) 内の XXX を抽出することです。これは、この関数が依存するすべてのモジュールです。
メソッド自体は複雑ではありませんが、この正規表現は単純ではありません:
deps を分析した後、モジュール定義をキャッシュに保存します:
define メソッドはモジュールを分析して格納するだけであり、モジュールを実行しないことに注意してください。
2. モジュールの実際の実行は require メソッド内で行われます。次にrequireを見てみましょう。
要するに、require メソッドは、定義定義が保存されているモジュール キャッシュ内で対応するモジュールを ID に基づいて検索し、それを実行してモジュール定義によって返されるメソッドを取得することです。
この大きなステップ全体の中で、詳細に説明する必要がある非常に重要なステップがあります:
Module.get(require.resolve(id))。
モジュールが必要な場合は、まずモジュールを見つける必要があります。 Module.get メソッドがこの役割を果たします。
cachedMods がない場合は、新しいモジュールを作成し、cachedMods にキャッシュします。
define メソッドと rquire メソッドは複雑ではないようです。 seajs を使用する主な理由は、モジュールのロード ロジックが少し複雑であることです。
3. seajs 実行の本当のエントリ ポイントは use メソッドです:
use メソッドを通じて、ここの ID からモジュールのロードと実行がトリガーされます。
ロードの重要なポイントは mod.load メソッドにあることがわかります。
load メソッドのコードは少し長くなります。主なロジックは、MOD の現在のステータスがロード中かロード中かを判断することです。
モジュールのコンフォート関数では、ステータスのデフォルト値が 0 であることがわかります。
ロードされていない新しいモジュールがここにあります: mod.status = STATUS.LOADING ステータスはロードに設定され、後続のロード ロジックが実行されます。
次のステップは、モジュールの依存関係 URL を取得することです
mod.resolve メソッド:
Module.resolve メソッドは基本的に、相対パス、設定されたパス、エイリアスなどを絶対パスに変換します。これ以上のコードは投稿されません。
モジュールの読み込みステータスを更新します。
モジュールをロードするためのロジック:
主に m.fetch メソッドですが、その中の他のロジックはここでは省略されます。
seajs.request が最終的にモジュール ファイルをロードすることがわかります。
すべての依存モジュールがロードされたら、MOD の onload メソッドを実行します
これが mod.onload() メソッドです
この時点で、seajs の中核となるロジックがほぼ見えてきました。参考までに、理解が曖昧な点や不正確な表現がありましたら、お気軽に一緒に議論してください。
以上がこの記事の全内容です。皆さんに気に入っていただければ幸いです。