- SPAで発生する「白画面問題」の正体
- SPAの画面はHTMLでは作られていない
- JavaScriptバンドルとは何か
- 白画面が発生する具体的なポイント
- なぜ開発環境では再現しないのか
- SSRとの決定的な違い
- JavaScriptバンドルと白画面の関係
- よくある誤解
- 実務で取るべき対策
- 運用上の注意
- 最後に
SPAで発生する「白画面問題」の正体
SPA(Single Page Application)を運用していると、一定確率で「画面が真っ白になって何も表示されない」という報告が来ます。しかも再現が難しく、開発環境では問題が起きないことも多いです。サーバは正常、APIも応答しているのにユーザには何も見えない。この現象は回線障害ではなく、JavaScriptバンドルとブラウザ実行順序に起因します。
結論から言うと、SPAの白画面問題は「描画失敗」ではありません。アプリケーションが起動していない状態です。HTMLは取得されていても、JavaScriptの読み込み・解析・実行のどこかで止まると、DOMが構築されず画面は空のままになります。
SPAの画面はHTMLでは作られていない
典型的なSPAのHTMLは次のような形です。
<body> <div id="app"></div> <script src="/assets/app.bundle.js"></script> </body>
ここにはコンテンツが存在しません。ブラウザがHTMLを表示しても、ユーザが見るべき情報はありません。すべてのUIはJavaScriptによって生成されます。
つまりSPAでは、
HTML表示 = 画面表示
ではありません。
JavaScript実行 = 画面表示
です。この構造が白画面の原因になります。
JavaScriptバンドルとは何か
現代のフロントエンドは、多数のモジュールをまとめた単一のファイルを配信します。これがJavaScriptバンドルです。ReactやVue、状態管理ライブラリ、ルータ、UIコンポーネントなどが1つのファイルに結合されています。
app.bundle.js ├ framework ├ router ├ store ├ components └ business logic
ブラウザはこの巨大なスクリプトを次の順番で処理します。
1. ダウンロード
2. 構文解析(Parse)
3. 実行(Evaluate)
このどこかで問題が起きると、アプリケーションは起動しません。
白画面が発生する具体的なポイント
1. ダウンロード失敗**
CDNキャッシュ不整合やネットワーク遮断によりbundle.jsが取得できない場合、ブラウザはdiv要素だけを持つHTMLを表示します。つまり白画面になります。
2. 構文エラー**
const user = await getUser();
トランスパイル設定の不備や古いブラウザでは、これだけで実行が停止します。JavaScriptは1つのエラーでスクリプト全体が止まります。
3. 実行時例外**
render(user.profile.name);
APIレスポンスの形式変更などでundefinedアクセスが起きると、初期描画前にクラッシュします。
なぜ開発環境では再現しないのか
開発環境では以下の条件が揃っています。
- 高性能PC
- 最新ブラウザ
- キャッシュがない
- 高速回線
しかし本番ユーザは違います。
- 古いAndroid端末
- 企業プロキシ
- 低速CPU
- 途中切断される通信
特に起きやすいのが「途中までダウンロードされたJS」です。ファイル破損が起きると構文解析エラーになります。サーバログには残りません。
SSRとの決定的な違い
SSRではHTMLに内容があります。
<h1>商品名</h1> <p>説明...</p>
JavaScriptが失敗しても、最低限の情報は表示されます。これをProgressive Enhancementと言います。SPAではこの退避経路が存在しません。
つまり白画面はバグではなく、SPAの設計特性です。
JavaScriptバンドルと白画面の関係
バンドルが大きくなるほど、白画面の確率は上がります。理由は単純で、処理時間と失敗確率が増えるからです。
- ダウンロード時間が伸びる
- パース時間が増える
- 実行時間が増える
- メモリ使用量が増える
スマートフォンでは、JS解析に数秒かかることもあります。その間、画面は何も表示されません。
よくある誤解
ローディングスピナーを出せば解決すると思われがちですが、スピナーはJavaScriptで描画されます。つまりJSが起動していない状態では表示できません。
また「APIが遅いから白画面」と判断されることも多いですが、API到達前に停止しているケースが多数です。
実務で取るべき対策
白画面対策は性能改善ではなく故障前提設計です。
- エラーバウンダリの設置
- コード分割(route-based splitting)
- 最小JSブートストラップ
- 互換性トランスパイル
- scriptのdefer指定
<script defer src="/app.bundle.js"></script>
さらに重要なのは、最低限のHTMLを返すフォールバックです。ログイン画面やメンテナンス情報をプレーンHTMLで返すだけでも、完全な白画面を避けられます。
運用上の注意
SPAではサーバ監視だけでは障害検知できません。ブラウザ側のエラー収集(Sentryなど)が必須になります。実際の障害の多くはサーバではなくクライアントで発生します。
最後に
SPAの白画面問題は実装ミスではなく、アプリケーションをブラウザに配置した結果です。ネイティブアプリが起動失敗するのと同じ性質を持っています。
SPAを採用するなら、「常に正しく起動する」前提ではなく、「起動に失敗することがある」前提で設計する必要があります。表示速度の最適化よりも、失敗時に何を見せるかを決めることが、白画面を減らす最も現実的な対策になります。