コード分割

Parcelは、設定なしでコード分割をサポートしています。これにより、アプリケーションのコードを別々のバンドルに分割し、必要に応じてロードできるため、初期バンドルのサイズが小さくなり、ロード時間が短縮されます。

コード分割は、通常のimportステートメントのように動作しますが、Promiseを返す動的なimport()構文の使用によって制御されます。これは、モジュールを非同期にロードできることを意味します。

動的インポートの使用

#

次の例は、動的インポートを使用して、アプリケーションのサブページを必要に応じてロードする方法を示しています。

pages/index.js
import("./pages/about").then(function (page) {
// Render page
page.render();
});
pages/about.js
export function render() {
// Render the page
}

import()はPromiseを返すため、async/await構文も使用できます。

pages/index.js
async function load() {
const page = await import("./pages/about");
// Render page
page.render();
}
load();
pages/about.js
export function render() {
// Render the page
}

ツリーシェイキング

#

Parcelが動的にインポートされたモジュールのどのエクスポートを使用するかを判別できる場合、そのモジュールから未使用のエクスポートをツリーシェイキングします。これは、awaitまたはPromiseの.then構文を使用して、静的プロパティアクセスまたは分割代入で機能します。

注: awaitの場合、未使用のエクスポートは、awaitがトランスパイルされない場合(つまり、最新のbrowserslist設定の場合)にのみ削除できます。

let { x: y } = await import("./b.js");
let ns = await import("./b.js");
console.log(ns.x);
import("./b.js").then((ns) => console.log(ns.x));
import("./b.js").then(({ x: y }) => console.log(y));

共有バンドル

#

アプリケーションの複数の部分が同じ共通モジュールに依存する場合、それらは自動的に個別のバンドルに重複排除されます。これにより、一般的に使用される依存関係をアプリケーションコードと並行してロードし、ブラウザーによって個別にキャッシュできます。

たとえば、アプリケーションに同じ共通モジュールに依存する<script>タグを持つ複数のページがある場合、これらのモジュールは「共有バンドル」に分割されます。このようにして、ユーザーがあるページから別のページに移動する場合、そのページの新しいコードのみをダウンロードする必要があり、ページ間の共通の依存関係はダウンロードする必要がありません。

home.html
<!doctype html>
<div id="app"></div>
<script type="module" src="home.js"></script>
home.js
import { createRoot } from 'react-dom';

createRoot(app).render(<h1>Home</h1>, app);
profile.html
<!doctype html>
<div id="app"></div>
<script type="module" src="profile.js"></script>
profile.js
import { createRoot } from 'react-dom';

createRoot(app).render(<h1>Profile</h1>, app);

コンパイル済みHTML

home.html
<!doctype html>
<div id="app"></div>
<script type="module" src="react-dom.23f6d9.js"></script>
<script type="module" src="home.fac9ed.js"></script>
profile.html
<!doctype html>
<div id="app"></div>
<script type="module" src="react-dom.23f6d9.js"></script>
<script type="module" src="profile.9fc67e.js"></script>

上記の例では、home.jsprofile.jsの両方がreact-domに依存しているため、個別のバンドルに分割され、両方のHTMLページに追加の<script>タグを追加することにより並行してロードされます。

これは、動的なimport()でコード分割されたアプリの異なるセクション間でも機能します。2つの動的インポート間で共有される共通の依存関係は分割され、動的にインポートされたモジュールと並行してロードされます。

設定

#

デフォルトでは、Parcelは共有モジュールがサイズしきい値に達した場合にのみ共有バンドルを作成します。これにより、非常に小さなモジュールを分割したり、HTTP/2でもオーバーヘッドのある追加のHTTPリクエストを作成したりすることを回避できます。モジュールがしきい値を下回っている場合は、ページ間で重複します。

Parcelには、一度に多数のリクエストでブラウザーに過負荷をかけることを回避するための最大並列リクエスト制限もあり、この制限に達するとモジュールが重複します。共有バンドルを作成する場合、より大きなモジュールがより小さなモジュールよりも優先されます。

デフォルトでは、これらのパラメーターはHTTP/2用に調整されています。ただし、これらのオプションを調整して、アプリケーションに対して上下させることができます。これは、プロジェクトルートのpackage.jsonで@parcel/bundler-defaultキーを構成することで実行できます。

package.json
{
"@parcel/bundler-default": {
"minBundles": 1,
"minBundleSize": 3000,
"maxParallelRequests": 20
}
}

使用可能なオプションは次のとおりです。

http minBundles minBundleSize maxParallelRequests
1 1 30000 6
2(デフォルト) 1 20000 25

このトピックの詳細については、web.devをご覧ください。

内部化された非同期バンドル

#

モジュールが同じバンドル内から同期および非同期の両方でインポートされる場合、個別のバンドルに分割するのではなく、非同期依存関係は「内部化」されます。つまり、重複を避けるために動的インポートと同じバンドル内に保持されますが、セマンティクスを維持するためにPromiseでラップされます。

このため、動的インポートは、依存関係が同期的に必要ないことを示す単なるヒントであり、新しいバンドルが作成されることを保証するものではありません。

重複排除

#

動的にインポートされたモジュールに、可能なすべての祖先にすでに存在する依存関係がある場合、それは重複排除されます。たとえば、ページが動的にインポートされたモジュールでも使用されているライブラリをインポートする場合、ライブラリは実行時にすでにページに存在するため、親にのみ含まれます。

手動共有バンドル

#

:手動共有バンドルは現在実験段階であり、変更される可能性があります。

デフォルトでは、Parcelは一般的に使用されるモジュールを自動的に「共有バンドル」に分割し、上記にリストされたシナリオでバンドルを作成します。ただし、特定の場合には、バンドルに何が含まれるか、誰がそのバンドルをリクエストできるかを正確に指定したい場合があります。

これらのシナリオには、以下が含まれますが、これらに限定されません...

手動共有バンドルは、プロジェクトルートのpackage.jsonで指定できます。assetsプロパティは、globのリストに設定する必要があります。これらのglobに一致する任意のアセットファイルパスは、手動共有バンドルに含まれます。

この例では、manual.jsから始まるグラフ内のすべてのJSアセットを含むベンダーバンドルを作成し、3つの並列HTTPリクエストに分割します。

package.json
{
"@parcel/bundler-default": {
"manualSharedBundles": [
{
"name": "vendor",
"root": "manual.js",
"assets": ["**/*"],
"types": ["js"],
"split": 3
},
],
},
}

オプションの完全なリストは次のとおりです。

注意してください!

手動共有バンドルを構成すると、Parcelによって通常実行されるすべての自動コード分割がオーバーライドされ、node_modulesを含むコードベース全体にマップされるため、意図しないロード順序の問題が発生する可能性があります。使用するglobに注意し、ファイルタイプごとに1つのバンドルのみを指定することをお勧めします。また、rootファイルを指定することをお勧めします。