Webpack ではバンドルするファイルを 3 つのアプローチで分けることができる。エントリーポイントを複数設けたり、webpack.config.js に splitChunks の設定を入れたりなどの他に、Dyanmic import を使うことでもファイルを分けることができる。詳しくはCode Splittingを参照。
Dyanmic importは ES2015 のimportが静的にライブラリを読み込むのに対して、動的に読み込む。たいていの場合普通の import で事足りる一方、多言語用のファイルとか、普段は必要なくて全部読み込むとファイルサイズが大きくなるとか、なくてもまあ基本的な機能に問題ないみたいなものは必要なときに動的にファイルを読み込みたい場合もある。そういったときに Dynamic Import を利用する。
Motivation and use cases
The existing syntactic forms for importing modules are static declarations. They accept a string literal as the module specifier, and introduce bindings into the local scope via a pre-runtime “linking” process. This is a great design for the 90% case, and supports important use cases such as static analysis, bundling tools, and tree shaking.
However, it’s also desirable to be able to dynamically load parts of a JavaScript application at runtime. This could be because of factors only known at runtime (such as the user’s language), for performance reasons (not loading code until it is likely to be used), or for robustness reasons (surviving failure to load a non-critical module). Such dynamic code-loading has a long history, especially on the web, but also in Node.js (to delay startup costs). The existing import syntax does not support such use cases.
Truly dynamic code loading also enables advanced scenarios, such as racing multiple modules against each other and choosing the first to successfully load.
実装的にはこんな感じになる(サンプルコード)。Dynamic import の部分があると webpack が自動的に code splitting してくれるけれど、split されたチャンク名をつけたい場合はファイル名の前にコメントをつける。
import(/* webpackChunkName: "hello" */ "./hello_world").then((module) => {
const hello = new module.HelloWorld();
hello.say();
});
TypeScript の場合は、Compiler Optionsで removeComments を true にしていると、webpack が split する前にコメントを消してしまうので removeComments を false にする必要がある(Production モードの場合、Webpack の minificationで最終的にコメントを消してくれる)。
Webpack はデフォルトで node_modules から読み込んだライブラリをvendors
の cacheGroup に分ける。Dynamic Import したファイルで node_modules からライブラリを読み込んだりするとvendors~hello.js
みたいな名前でファイルを分割する。vendors にファイルを分けたくない場合は、cacheGroup で vendors の設定を false にする。
あと、cacheGroup の名前と chunk の名前の間の delimiter はデフォルトで~
になっている。通常これで問題ないけど、AWS の CloudFront で cache を invalidate しようすると valid なファイル名じゃないとエラーになるので、変更する必要がでるかもしれない。そういうときにはautomaticNameDelimiter
の設定で変更することができる。
optimization: {
namedChunks: true,
splitChunks: {
automaticNameDelimiter: '-',
cacheGroups: {
vendors: false
}
}
},
というメモ。