ゲームを開いた瞬間、ブラウザの中で何が起きているか:HTMLの読み込みから最初の描画まで
遊びを見つける執筆にClaudeを使用しています。

ゲームのカードを押すと、少し間があって盤面やタイトルが現れます。この「少し」の中で、ブラウザは外側の枠を用意し、HTMLを上から読み、スタイルを組み合わせ、画面のどこに何を置くかを計算し、最後に色を塗っています。ゲームが動き出す前に、これだけの段階が順に進んでいます。 この記事では、その順番を追います。特に押さえたいのは、「ページが最初に描かれた瞬間」と「ゲームの最初の1コマが出た瞬間」が別物だという点です。前者はブラウザの仕事で、後者はゲームのJavaScriptの仕事です。この違いが分かると、「開いたのに真っ白」「タイトルは出たのに動かない」といった場面が、どの段階の話なのか見分けられます。 なお、実際にかかる時間は端末や回線、作品の大きさで変わります。この記事では時間の数字は挙げません。代わりに、読者が自分の環境で順番と所要を見る手順を最後に示します。
外側の枠が先に用意される:アソバースの再生画面
アソバースでは、ゲームはサイトのページの中に埋め込まれて動きます。確認済みの範囲で言えるのは、ゲームがsandbox付きのiframeで実行されることと、アップロードされたコードがメインサイトとは別のオリジンから配信されることです。
iframeは、ページの中に別のページをはめ込む仕組みです。sandboxはその中のコードにできることを絞る指定で、オリジンは「どこから配信されたか」を表すアドレスの単位です。メインサイトとゲームを別のオリジンに分けることで、ゲームのコードがサイト本体の情報に触れにくくなります。
つまり「ゲームを開く」とは、サイト側の画面が先に表示され、その枠の中でゲーム用の読み込みが別に始まる、という二段構えです。枠だけ先に見えて中身が空という状態があり得るのは、この構造のためです。
投稿の条件からも、読み込み対象の姿が分かります。入口は直下のindex.htmlで、素材は相対パスで参照します。サーバー用コードやサービスワーカーは対象外です。「HTMLとその素材だけをファイルとして読む」形に絞られているわけです。
HTMLは上から順に読まれる
ブラウザは、取得したHTMLを先頭から順に解析して、ページの構造(DOM)を組み立てます。ここで知っておきたい規則が三つあります。
- 通常の <script> に出会うと、ブラウザは原則としてそのスクリプトを実行し終えるまで解析を止めます。重い初期化処理を <head> に書くと、その間は何も組み上がりません。
- defer や async を付けたスクリプト、type="module" のスクリプトは、解析を止めずに取得できます。実行のタイミングは、種類ごとに規則が異なります。
- CSSは、読み込み終わるまで描画を待たせるのが基本です。スタイルが未確定のまま描くと、見た目が途中で大きく変わってしまうためです。
画像や音声のような素材は、HTMLの解析とは別に取得されます。ZIPで投稿して素材を相対パスで読む作品は、素材の数だけ取得が増えます。公式13作品は独立したHTMLで外部通信なしに動くと確認されており、読み込む相手は作品自身のファイルに限られます。
アソバースの確認済み事項には、アップロードしたゲームにSDKが自動で追加されるとあります。ただ、それがどの位置でどの順に読まれるかは確認済みの範囲にありません。この部分は、後述の方法でNetworkの一覧を見て確かめてください。URLで投稿された作品では、SDKは作者が読み込んだ場合にだけ使えます。
「最初の描画」までの道のり
DOMができ、CSSが読み込まれると、ブラウザは次の段階に進みます。
- DOMとスタイルを突き合わせ、どの要素にどの見た目が当たるかを決める。
- 各要素の位置と大きさを計算する(レイアウト)。
- 色や文字、画像を塗る(ペイント)。
- 塗った層を重ねて画面に出す(合成)。
ここで初めて、画面に何かが映ります。ゲームのタイトルや、空の盤面の枠が見えるのはこの時点です。
ただし、<canvas>を使うゲームでは、canvas要素は枠として表示されても、中身はJavaScriptが描くまで空です。ブラウザの最初の描画は済んでいても、ゲームの最初の1コマはまだ出ていません。DOMのボタンや文字で盤面を組むゲームなら、JavaScriptが要素を作った時点で描画に載ります。どちらの作り方でも、最初の1コマはJavaScriptの初期化が終わってから現れます。
ゲームが動き出す:初期化、保存、音
最初の描画のあと、あるいはそれと前後して、ゲームのJavaScriptが初期化を進めます。画面の部品を作る、設定を読む、入力の受付を始める、といった処理です。連続して動く作品は、requestAnimationFrameでループを始めます。これは「次の描画の直前に、この関数を呼んでほしい」とブラウザに頼む仕組みで、多くの画面では1秒に60回前後のペースで呼ばれます。
設計から読み取れること
13作品の確認済み事項から、起動時の仕事を推測できる点があります。ただし、実際の処理の順序は確認済みではないため、「そう作られているはず」という読み取りです。
- 保存があるのは余白の庭、WAVE / WAVE、かたちのあいだの3作品です。以前の庭を引き継げるのですから、開くときに保存内容を読み出して画面を復元する処理が必要です。古い保存(version1)を新しい形式(version2)へ移行する仕様もあります。保存のない作品は、毎回まっさらな状態から始まります。
- 他の10作品の記録や録音は、画面を開いている間だけ残ります。起動時に読み出す対象がないので、初期化は軽い構成になりやすいと言えます。
- サイトの日本語/英語設定に合わせて表示が切り替わり、「動きを抑える」設定にも対応します。起動時にこれらの設定を参照して、最初の画面の文言や動きを決めていると考えられます。
- 音を使う作品について、多くのブラウザは利用者の操作より前に音を鳴らすことを制限しています。そのため、音のある作品でも最初の一音は、鍵盤を押す、始めるを押すといった操作の後になるのが自然です。こだまの森のように音なしでも遊べる作品は、この制限や音が出せない環境でも進行できる設計です。
どの作品がどの順序で何を読むかは、確認済みの範囲では分かりません。この部分は、作品を開いて確かめる領域です。
なお、プレイ回数は「作品起動の実測回数」で、同じ端末・作品の30分以内の再起動は重複が除かれます。何をもって起動とするかの細部は、現在の案内で確認してください。
自分の環境で順番を見る手順
次の小さなHTMLを使うと、読み込みから描画までの主な節目の時刻を、自分の画面に表示できます。performance.now()は、ページの読み込み開始からの経過ミリ秒を返します。
<!doctype html>
<meta charset="utf-8">
<title>起動の順番</title>
<style>#log{white-space:pre;font:16px monospace}</style>
<body>
<p id="log"></p>
<script>
const log = document.getElementById("log");
const mark = (name) => {
log.textContent += name + ": " + Math.round(performance.now()) + "ms\n";
};
mark("script実行(body内)");
document.addEventListener("DOMContentLoaded", () => mark("DOMContentLoaded"));
window.addEventListener("load", () => mark("load"));
requestAnimationFrame(() => {
mark("最初のrAF");
requestAnimationFrame(() => mark("次のrAF"));
});
</script>
</body>DOMContentLoadedはHTMLの解析とDOM構築が済んだ時点、loadは画像などの素材も含めて読み終えた時点です。rAFは描画の直前に呼ばれます。このファイルに保存して、ブラウザで開いてください。
記録の取り方は次のとおりです。
- 同じ条件で5回ほど開き直し、各行の値を書き留めます。1回の値より、順番と幅が大事です。
- 値は端末や負荷で揺れるので、平均より「毎回同じ順番か」を見ます。
- <script>の前に重い処理(巨大な繰り返しなど)を足して、DOMContentLoadedやrAFがどう後ろにずれるかを比べます。解析が止まる様子を自分の目で確かめられます。
ブラウザの開発者ツールも使えます。
- Networkタブ:キャッシュを無効にして再読み込みすると、取得したファイルが順に並びます。アソバースの作品を開いた場合は、ゲーム本体以外にどんなファイルが読まれているか、SDKがいつ現れるかを確認できます。
- Performanceタブ:記録しながら再読み込みすると、解析、スタイル計算、レイアウト、ペイント、スクリプト実行が時間軸に並びます。どの段階が長いかを見て、「ブラウザの待ち」か「ゲームの初期化」かを切り分けます。
読み方の目安はこうです。DOMContentLoadedまでが長いなら、先頭付近の重いスクリプトや大きなCSSを疑います。そこは早いのにrAFが遅いなら、初期化処理が主役です。loadだけが遅いなら、画像や音の素材が重い可能性があります。
誤りやすい点もあります。キャッシュが残ると2回目以降が極端に速くなります。ローカルで開いた結果と、アソバース上のiframeで開いた結果は、配信経路が違うため同じとは限りません。拡張機能が入ったブラウザでは、余計なスクリプトが混ざることもあります。
次の行動
上のHTMLを保存して、5回開き直し、DOMContentLoaded・load・rAFの並びを書き留めてみてください。続いて、好きな公式作品をNetworkタブを開いた状態で起動し、読み込まれるファイルの一覧と最初に画面が出る瞬間を見比べてみてください。作品を自分で作る方は、自作のゲームでも同じ確認を行うと、重い部分を見つけやすくなります。
参考資料
- MDN Web Docs「ブラウザはどのようにウェブページを表示するか」「Performance API」
- WHATWG HTML Living Standard(スクリプトの読み込みと実行に関する節)
- Chrome DevTools ドキュメント(Network、Performance パネル)

