以前のアーキテクチャは非常にシンプルなバージョンで、通常のステージのローダーのみをサポートしていました。ピッチングローダーは考慮されていませんでした。旧バージョンの基本的な概念は、通常のローダーをRust側から呼び出すことができるネイティブ関数に変換することです。さらに、パフォーマンス上の理由から、RspackはJS側でローダーを構成して、Node/Rust間の通信のパフォーマンス問題を軽減しています。
この新しいアーキテクチャでは、ローダーはネイティブ関数に直接変換されません。代わりに、識別子を活用することで、Webpackのローダーランナーがローダーを解決する方法とほぼ同じになります。RspackがJSローダーを呼び出すたびに、識別子がNode側で渡されたハンドラーに渡されて処理されます。この実装では、パフォーマンス上の理由から、JSローダーを構成する機能も維持されています。
このリファクタリングでは、他に破壊的な変更は導入されていません。そのため、後方互換性があります。アーキテクチャの変更により、構成可能なピッチングローダーを実装することもできます。
ピッチングローダーは、ローダーパイプラインのフローを変更する手法です。通常、インラインローダー構文で使用して、別のローダーパイプラインを作成します。 style-loaderなど、後続のローダーの評価結果を使用する可能性のあるローダーはこの手法を使用する場合があります。同じ機能を実現する他の手法もありますが、この記事のトピックから外れています。
詳細については、ピッチングローダーを参照してください。
ローダーの元の実装では、Rspackは最初に通常のローダーを変換し、Rust側に渡します。モジュールをビルドする手順で、これらのローダーが直接呼び出されます。
ローダーランナーはRust側にのみ存在し、Rust側からローダーを直接実行します。このメカニズムは、Webpackのローダーランナーを構成されたローダーに使用することに大きな制限があります。
新しいアーキテクチャでは、ローダーリクエストをRustコアからJS側にあるディスパッチャーに委任します。ディスパッチャーはローダーを正規化し、Webpackのローダーランナーの修正バージョンを使用してこれらを実行します。
ピッチまたは通常のローダー関数はRust側に渡されません。代わりに、各JSローダーには、それぞれを一意に表す識別子があります。モジュールがモジュールを処理するためのローダーを要求する場合、Rspackは識別子とオプションをJS側に渡して、Webpackのようなローダーランナーにトランスフォームを処理するように指示します。これにより、独自のローダーコンポーザーを作成する際の複雑さも軽減されます。
オプションは通常クエリに変換されますが、一部のオプションにはシリアル化できないフィールドが含まれています。RspackはWebpackによって作成された_ローダー識別子_を再利用して、オプションを一意に識別し、後の読み込みプロセスで復元します。
前述のように、各ローダーにはピッチと通常の2つのステップがあります。パフォーマンスに優れた相互運用性を実現するには、RustとJS間の通信を可能な限り最小限に抑える必要があります。通常、ローダーの実行手順は次のようになります。
上記のローダーの実行順序は次のようになります。
上記の例にはJSローダーは含まれていませんが、たとえば、JS側に登録されているこれらのローダーをマークするとします。
実行順序は変わりませんが、Rspackはステップ2/3/4をまとめて1回の通信で構成します。