最終編集
これのtl; dr解決は、それが不可能であるということです。以下の一番上の答えにはいくつかの良い情報がありますが。
contacts.js
からの以下のコードを検討してください。これは動的にロードされるモジュールであり、コードの他の場所でSystem.import
を使用してオンデマンドでロードされます。
SharedUtil1
が他のモジュールでも使用されており、それらも動的にSystem.import
でロードされている場合、SharedUtility1
除外これらのモジュールのすべてから、オンデマンドでのみ初回必要ですか?
System.import
のトップレベルのSharedUtil1
は、エクスポートがそれに依存しているため機能しません。エクスポートは、モジュールのコードのトップレベルにのみ配置でき、コールバックには配置できません。
これはWebpackで可能ですか?私はバージョン2.0.7ベータ版を使用しています。
import SharedUtil1 from '../../SharedUtilities/SharedUtility1';
class Contacts{
constructor(data){
this.data = data;
this.sharedUtil1 = new SharedUtil1();
}
}
export default Contacts;
更新1
バンドルローダー が私が望んでいたものだと思いましたが、非同期でロードが完了すると、インポートされたモジュールを、実際のモジュールに到達するためにコールバックで呼び出す別の関数に変換します。これは、コードに重大な変更を加えずにモジュールXを非同期的にロードすることはできないことを意味します。もちろん、最初に説明した問題に戻ったという事実は言うまでもなく、トップレベルのモジュールが今非同期に依存している場合はロードされた依存関係。エクスポートはトップレベルである必要があるため、エクスポートする方法はありません。
Webpackには、依存関係Xが必要に応じてオンデマンドでロードされ、それをインポートするインポートされたモジュールがインポートプロセスを透過的に待機することを示す方法はありませんか?このユースケースは、リモートで大規模なアプリケーションのsine qua nonになると思うので、何かが足りないと思う必要があります。
更新2
Peterの回答によると、commonChunkプラグインはエンドポイント間でのコードの共有に関連しており、require.ensure
はロードされたコードをコールバックに配置するため、重複排除を機能させようとしました。これにより、ES6 export
ingに依存するコード。
重複排除に関しては、contacts.js
とtasks.js
の両方が同じsharedUtilをロードします。
import SharedUtil1 from '../../sharedUtilities/sharedUtility1';
私はwebpackをとして実行してみました
webpack --optimize-dedupe
また、追加することによって
plugins: [
new webpack.optimize.DedupePlugin()
]
webpack.configに。どちらの場合も、sharedUtilコードは引き続き連絡先バンドルとタスクバンドルの両方に配置されます。
あなたのブログ投稿を読んだ後、私はついにあなたが意図したことを理解しました。 「トップレベルの依存関係」という言葉に少し混乱しました。
2つのモジュール(async-a
とasync-b
)があり、どこからでもオンデマンドでロードされ(ここではモジュールmain
)、両方とも共有モジュール(shared
)。
- - -> on-demand-loading (i. e. System.import)
---> sync loading (i. e. import)
main - - -> async-a ---> shared
main - - -> async-b ---> shared
デフォルトでは、webpackは次のようなチャンクツリーを作成します。
---> chunk uses other chunk (child-parent-relationship)
entry chunk [main] ---> on-demand chunk 1 [async-a, shared]
entry chunk [main] ---> on-demand chunk 2 [async-b, shared]
これは、shared
<async-a/b
の場合、またはasync-a
とasync-b
の両方が同じユーザーによって使用される可能性が低い場合に問題ありません。これは最も単純な動作であり、おそらく予想される動作であるため、デフォルトです。1つのSystem.import
=> 1つのチャンクです。私の意見では、それは最も一般的なケースでもあります。
ただし、shared
> = async-a/b
であり、ユーザーがasync-a
とasync-b
をロードする可能性が高い場合は、より効率的なチャンク化オプションがあります:(少し難しい視覚化する):
entry chunk [main] ---> on-demand chunk 1 [async-a]
entry chunk [main] ---> on-demand chunk 2 [async-b]
entry chunk [main] ---> on-demand chunk 3 [shared]
When main requests async-a: chunk 1 and 3 is loaded in parallel
When main requests async-b: chunk 2 and 3 is loaded in parallel
(chunks are only loaded if not already loaded)
これはデフォルトの動作ではありませんが、アーカイブするためのプラグインがあります:非同期モードのCommonChunkPlugin
。チャンクの束の中から共通/共有モジュールを見つけ、共有モジュールを含む新しいチャンクを作成します。非同期モードでは、元の(ただし現在は小さい)チャンクと並行して新しいチャンクをロードします。
new CommonsChunkPlugin({
async: true
})
// This does: (pseudo code)
foreach chunk in application.chunks
var shared = getSharedModules(chunks: chunk.children, options)
if shared.length > 0
var commonsChunk = new Chunk(modules: shared, parent: chunk)
foreach child in chunk.children where child.containsAny(shared)
child.removeAll(shared)
foreach dependency in chunk.getAsyncDepenendenciesTo(child)
dependeny.addChunk(commonsChunk)
CommonsChunkPluginには、モジュールがいつスレッド化されるかをminChunks
として定義するshared
オプションがあることに注意してください(モジュールを選択するためのカスタム関数を自由に提供してください)。
セットアップと出力を詳細に説明する例を次に示します。 https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk
そして、より多くの構成を持つ別のもの: https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk-advanced
私があなたを正しく理解していれば、異なるコードチャンクが依存関係として宣言したときに同じ依存関係が複数回読み込まれるのを防ぎたいと思います。
はい、これは可能です。それを行う方法は、アプリケーションのコンテキストと、ES6またはES5のどちらにあるかによって異なります。
Webpack1はECMAScript 5で構築されており、通常、モジュールのエクスポートとインポートにCommonJSまたはRequireJS構文のいずれかを使用します。この構文を使用する場合、次の機能を使用してコードの重複を防ぐことができます。
webpackドキュメント から:
クールな依存関係ツリーを持つライブラリを使用すると、一部のファイルが同一になる場合があります。 Webpackはこれらのファイルを見つけて、重複排除することができます。これにより、重複するコードがバンドルに含まれるのを防ぎ、代わりに実行時に関数のコピーを適用します。 セマンティクスには影響しません。
強調は私のものであり、ソースからではありません
ドキュメントに記載されているように、コード分割は変更されません。 _sharedUtil1
_を必要とする各モジュールは、通常どおりrequire
を宣言する必要があります。同じ依存関係が複数回読み込まれるのを防ぐために、実行時にファイルを含める前に、webpackがファイルの重複を明示的にチェックするようにするwebpack設定が有効になっています。
このオプションは、_--optimize-dedupe
_ respで有効になります。 new webpack.optimize.DedupePlugin()
webpackドキュメント から:
_
require.ensure
_関数は、追加の3番目のパラメーターを受け入れます。これは文字列でなければなりません。 2つのスプリットポイントが同じ文字列を渡す場合、それらは同じチャンクを使用します... _require.include
_は、モジュールが複数の子チャンクにある場合に役立ちます。親の_require.include
_にはモジュールが含まれ、子チャンクのモジュールのインスタンスは表示されなくなります。
つまり、モジュールのロードはコンパイルの後半まで延期されます。これにより、重複する定義を含める前に削除できます。ドキュメントには例が記載されています。
webpackドキュメント から:
CommonsChunkPlugin
は、複数のエントリチャンクで発生するモジュールを新しいエントリチャンク(コモンズチャンク)に移動できます。ランタイムもコモンズチャンクに移動されます。これは、古いエントリチャンクが最初のチャンクになったことを意味します。
これは、複数のページ間でチャンクを共有することに非常に固有であり、他の状況では関係ありません。
高度なモジュールインポート機能のサポートは...進行中の作業です。物事がどこにあるかを知るには、次のリンクを参照してください。
ES6モジュールとwebpackの概要は次のとおりです。 TypeScriptとWebpackを備えたES6モジュール
上記の情報はすぐに古くなる可能性があります。
あなた自身の正気のために、私は提案します:
最適化が重要な場合:Webpack 2が安定してリリースされたら、CommonJS/RequireJS構文に戻し、ECMA Script6にアップグレードします。
ECMA Script 6構文が重要な場合:標準のECMA Script 6インポートエクスポート形式を使用し、利用可能になったときに最適化機能を追加します。
シル不安定なwebpack2で高度なモジュール読み込み機能を試して使用するには、フラックスが多すぎます。問題が解決し、いくつかの本当に優れたプラグインが利用可能になるのを待ってから、試してみてください。
_System.import
_はWebpackで非推奨になりました。 Webpackは、promiseにポリフィルを必要とするimport()
を優先するようになりました。