- コードスプリッティングは「軽くする技術」ではない
- まずSPAの初期表示で何が起きているか
- コードスプリッティングの仕組み
- ウォーターフォールでの変化
- 「効くタイミング」はページ遷移時
- よくある失敗:分割しすぎ
- prefetchと組み合わせたときに真価が出る
- 注意点:LCPが悪化するケース
- どう考えるべきか
コードスプリッティングは「軽くする技術」ではない
SPAのパフォーマンス改善として必ず登場するのがコードスプリッティング(Code Splitting)です。
「JavaScriptを分割すると速くなる」と説明されることが多いですが、この理解は半分正しく、半分間違っています。
コードスプリッティングはファイルサイズを減らす技術ではありません。ダウンロードの順序を変える技術です。
そして、効くタイミングを誤解すると「導入したのに遅くなった」という結果になります。
まずSPAの初期表示で何が起きているか
コードスプリッティングがないSPAでは、初回アクセス時にブラウザは次の処理を行います。
1. index.html取得
2. main.js取得
3. main.js実行
4. API通信
5. 画面描画
重要なのは、main.jsのダウンロードと実行が完了するまで画面が作られない点です。
つまりJSは「アプリ本体」です。取得が遅れると何も始まりません。
ウォーターフォールで見ると、次のような直列処理になります。
| 順番 | 処理 |
| 1 | HTML取得 |
| 2 | 巨大JSダウンロード |
| 3 | JS解析・実行 |
| 4 | API通信 |
| 5 | 描画 |
ここに1MBのJSがあると、それだけで数秒止まります。
コードスプリッティングの仕組み
コードスプリッティングでは、JSを機能単位で分割します。
例:
- main.js(共通処理)
- home.chunk.js
- dashboard.chunk.js
- settings.chunk.js
ルーティングに応じて必要なチャンクだけを読み込みます。
const Dashboard = React.lazy(() => import("./Dashboard"));
ここで初めて重要な変化が起きます。
「最初に全部読む」から「必要な時に読む」へ変わります。
ウォーターフォールでの変化
コードスプリッティング後の初回アクセスは次の順序になります。
| 順番 | 処理 |
| 1 | HTML取得 |
| 2 | main.js取得(小さい) |
| 3 | 初期画面描画 |
| 4 | 必要なchunk取得 |
つまり描画が前に移動します。
ここが「速くなった」と感じる理由です。
処理時間は減っていません。描画開始が前倒しされただけです。
「効くタイミング」はページ遷移時
コードスプリッティングが最も効果を発揮するのは初回表示ではありません。
ページ遷移時です。
遷移前:
1. クリック
2. dashboard.chunk.js取得
3. 実行
4. 表示
このときブラウザは必要な分だけ取得します。
もし全JSが1ファイルなら、遷移のたびに巨大な処理を抱えることになります。
つまりコードスプリッティングは「初回高速化」ではなくルーティング高速化の技術です。
よくある失敗:分割しすぎ
コードスプリッティングの典型的な失敗があります。
チャンクを細かくしすぎることです。
- componentA.js
- componentB.js
- componentC.js
一見軽そうですが、HTTPリクエストが増えます。
結果としてウォーターフォールが階段状になります。
| 問題 | 結果 |
| 通信回数増加 | TTFB増加 |
| 接続数制限 | 待機発生 |
| ヘッダ往復 | RTT増加 |
モバイル回線では特に悪化します。
「小さいファイルが大量」が最も遅くなるパターンです。
prefetchと組み合わせたときに真価が出る
コードスプリッティング単体では、遷移時に待ち時間が発生します。
ここで登場するのがprefetchです。
- 画面表示中に次ページのchunkを取得
- クリック時には既にキャッシュ済み
これにより遷移は瞬間になります。
Next.jsが速く感じるのは、コードスプリッティングとprefetchが同時に働いているためです。
つまりコードスプリッティングは単独では完成しません。
「いつ取得するか」とセットで初めて効果が出ます。
注意点:LCPが悪化するケース
コードスプリッティングは万能ではありません。
ファーストビューのコンポーネントを分割すると逆効果になります。
- ヒーロー画像コンポーネント
- ナビゲーション
- メイン記事
これらをlazy loadすると、描画に追加通信が必要になります。
結果としてLCP(Largest Contentful Paint)が遅れます。
重要なUIは分割しない方が良い場合が多いです。
どう考えるべきか
コードスプリッティングは「軽量化」ではありません。
ユーザーが必要になる順番に読み込む設計です。
まとめると次のようになります。
- 初回表示:小さな本体だけ先に
- 遷移:必要部分のみ取得
- 事前取得:prefetchで待ち時間を隠す
パフォーマンス改善とは、処理量を減らすことではなく「待たせる場所を変えること」です。
コードスプリッティングはその代表的な手法であり、ネットワークの流れを設計する技術だと捉えると、どこで使うべきか判断しやすくなります。