HTMLのライフサイクル
Ethan Miller
Product Engineer · Leapcell

**HTMLネイティブライフサイクル(Lifecycle)**は通常、ブラウザがウェブページをロードして処理する際に経験するイベントとステージを指します。HTML自体はマークアップ言語であり、JavaScriptのようなライフサイクルフックはありませんが、HTMLライフサイクルイベントは実際にはDOM(Document Object Model)とのJavaScriptの相互作用を通じて管理されます。
HTMLの解析
ブラウザがウェブページをロードすると、サーバーからHTMLファイルを受信し、解析を開始します。この段階で、ブラウザはDOMツリー(Document Object Model)を作成し、HTMLを操作可能なDOMオブジェクトに変換します。
厳密に言えば、HTML解析はページロードプロセスにおける不可欠な段階ですが、JavaScriptを介して直接キャプチャまたはリッスンできないため、従来の意味での「ライフサイクルイベント」のカテゴリには該当しません。ただし、より広い視点から見ると、HTML解析はページ全体のライフサイクルにおいて不可欠な部分であり、HTMLライフサイクルに関する議論において重要な要素となります。
このプロセスはブラウザの内部で行われるため、開発者はこのフェーズを直接リッスンすることはできません。ただし、HTML構造を最適化し、ブロッキングリソース(JavaScriptファイルなど)を最小限に抑えることで、解析速度を向上させることができます。
外部リソースのロード
ブラウザがHTMLを解析する際、外部リソースに遭遇します。リソースの種類、ロード方法(同期または非同期)、優先度に応じて、ブラウザはページのロードとレンダリングをどのように続行するかを決定します。この挙動は、ページのレンダリング順序と、ユーザーに表示されるコンテンツのロード時間に直接影響します。
異なるリソースタイプは、ページ解析とレンダリングに影響を与える異なるロード動作をします。
-
CSSのロード: ブラウザが
<link>
タグに遭遇すると、CSSファイルが完全にロードされ、解析されるまでページのレンダリングを一時停止します。CSSは、CSSファイルなしではページレイアウトとスタイルが正しくレンダリングできないため、レンダリングブロッキングリソースと見なされます。 -
JavaScriptのロード: デフォルトでは、ブラウザが
<script>
タグに遭遇すると、JavaScriptファイルがロードされ、実行されるまでHTML解析を停止します。これは同期ロードとして知られています。同期的にロードされたJavaScriptはHTML解析をブロックし、DOMContentLoaded
およびload
イベントのタイミングに影響を与えます。
全体として、外部リソースのロードは、外部リソースのロードが解析、レンダリング、およびDOMContentLoaded
やload
などの重要なライフサイクルイベントのトリガーに影響を与えるため、ページライフサイクルと密接に関連しています。外部リソースのロード時間が短いほど、ライフサイクルイベントがトリガーされるのが早くなります。
readyStateとreadystatechange
readyState
とreadystatechange
は、ドキュメントとネットワークリクエスト(AJAXリクエストなど)の状態を追跡するために使用される2つの主要なブラウザ属性とイベントです。これらは、開発者がウェブページのロードプロセスのさまざまな段階を理解し、これらの段階で対応する操作を実行するのに役立ちます。これらは主に、ドキュメントのロードとネットワークリクエスト(例:XMLHttpRequest
)のコンテキストで使用されます。
document.readyState
document.readyState
プロパティは、ドキュメントの現在の状態を表し、異なるドキュメントのロード段階に対応する3つの可能な値を持ちます。
loading
: ドキュメントはまだロード中で、HTMLはまだ解析されています。DOMツリーはまだ完全に構築されていません。外部リソース(画像やスタイルシートなど)はロードまたは処理されていない可能性があります。interactive
: ドキュメントのHTMLは完全にロードおよび解析され、DOMツリーが構築されました。ただし、スタイルシート、画像、その他のリソースはまだ完全にロードされていない可能性があります。complete
: HTML、CSS、JavaScript、画像、サブフレームを含む、ページ上のすべてのリソースが完全にロードおよび処理されました。ページは完全に準備ができています。
document.readyState
を使用すると、開発者はドキュメントのロード状態を確認し、異なる状態に基づいて対応するアクションを実行できます。 例:
if (document.readyState === 'complete') { // ページは完全にロードされました。ページ操作を実行します }
readystatechange
イベント
readystatechange
イベントは、ドキュメントのreadyState
が変更されたときにトリガーされます。 開発者はreadystatechange
イベントをリッスンして、異なるロード段階で特定のロジックを実行できます。 例えば:
document.addEventListener('readystatechange', function () { if (document.readyState === 'interactive') { // DOMツリーが完全に構築されました。DOM操作が可能になりました console.log('DOM is fully parsed'); } else if (document.readyState === 'complete') { // すべてのリソースを含むページ全体が完全にロードされました console.log('Page and resources are fully loaded'); } });
以下は、document.readyState
とreadystatechange
を使用して、さまざまなドキュメントのロード段階を追跡するHTMLの例です。このページには、基本的なHTML要素が含まれており、さまざまなreadyState
段階で対応するコンテンツまたは情報を表示します。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document ReadyState Example</title> <style> body { font-family: Arial, sans-serif; padding: 20px; } .status { font-size: 1.2em; color: #333; margin: 20px 0; } img { max-width: 100%; height: auto; } </style> </head> <body> <h1>Hello World</h1> <script> function updateStatus() { console.log(document.readyState); switch (document.readyState) { case 'loading': console.log('loading'); break; case 'interactive': console.log('interactive'); break; case 'complete': console.log('complete'); break; } } updateStatus(); document.addEventListener('readystatechange', updateStatus); </script> </body> </html>
上記のコードの出力:
loading
interactive
complete
DOMContentLoadedイベント
DOMContentLoaded
イベントは、HTMLドキュメントのロードプロセス中にブラウザによってトリガーされるキーイベントです。これは、HTMLドキュメント内のすべての要素が完全に解析され、DOMツリーが構築されたことを意味します。ただし、画像、スタイルシート、ビデオなどの外部リソースは、ロードが完了していない可能性があります。これは、DOMContentLoaded
とload
イベントの主な違いです。
DOMContentLoaded
イベントはdocument
オブジェクトで発生し、addEventListener
を使用してキャプチャする必要があります。
document.addEventListener('DOMContentLoaded', () => {});
DOMContentLoaded
イベントは、ブラウザがHTMLドキュメントの解析を終了し、すべてのDOMノードを生成したときにトリガーされます。ただし、外部リソース(画像、ビデオ、スタイルシート、フォントファイルなど)が完全にロードされる必要はありません。
たとえば、ページに大きな画像が含まれている場合、DOMContentLoaded
イベントは画像が完全にロードされる前に発生します。この時点で、DOMツリーは完全に構築されており、開発者はページのDOM要素を操作およびアクセスできます。次に例を示します。
<script type="text/javascript"> function ready() { console.log('DOM is ready.'); const img = document.querySelector('#img'); // この時点で、画像は完全にロードされていない可能性があります(キャッシュされている場合を除く)。 // したがって、そのサイズは0x0になります。 console.log(`Image size: ${img.offsetWidth}x${img.offsetHeight}`); } document.addEventListener('DOMContentLoaded', ready); </script> <img id="img" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
このコードの出力は次のようになり、画像がロードされる前にDOMが完全に解析されます。
DOM is ready.
Image size: 0x0
ページに同期JavaScriptファイルがある場合(つまり、async
またはdefer
属性のないスクリプト)、ブラウザは<script>
タグに遭遇するとHTML解析を一時停止し、スクリプトの実行を待ってから解析を続行します。これにより、DOMContentLoaded
イベントのトリガーが遅延します。
<script type="text/javascript"> document.addEventListener('DOMContentLoaded', () => { console.log('DOM ready!'); }); </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"></script> <script type="text/javascript"> console.log('Library loaded, inline script executed'); </script>
出力順序:
Library loaded...
DOM ready!
DOMContentLoaded
イベントをブロックしないスクリプトは次のとおりです。
async
属性を持つスクリプトdocument.createElement('script')
を使用してウェブページに動的に追加されたスクリプト
window.onloadイベント
load
イベントは、スタイル、画像、その他のリソースを含むページ全体が完全にロードされると、window
オブジェクトでトリガーされます。このイベントは、onload
プロパティを使用してキャプチャできます。
次に、window.onload
がすべての画像が完全にロードされるまで待機するため、画像のサイズが正しく表示される例を示します:
<script type="text/javascript"> window.onload = function () { console.log('Page loaded'); // この時点で、画像は完全にロードされています console.log(`Image size: ${img.offsetWidth}x${img.offsetHeight}`); }; </script> <img id="img" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />
このコードの出力は、onload
がすべてのリソースがロードを終了するまで待機するため、以前の例とは異なります。
Page loaded
Image size: 544x184
window.onbeforeunloadイベント
beforeunload
イベントは、ページがアンロードされようとしている直前にトリガーされます(たとえば、ユーザーが別のページに移動したり、タブを閉じたり、ページを更新したりする場合)。このイベントを使用すると、開発者はユーザーにページを離れて本当に良いかどうかを確認するように求めることができます。これは通常、保存されていないデータを保存するようにユーザーにリマインドしたり、潜在的なデータ損失について警告したりするために使用されます。
ブラウザでは、このイベント中に短いメッセージが表示され、ページを離れても良いかどうかをユーザーに確認できます。たとえば、ユーザーが保存されていないフォームにコンテンツを入力した場合、開発者はbeforeunload
を使用して、誤ったページの閉じまたは更新を防ぐことができます。
最新のブラウザは、カスタムプロンプトメッセージを表示しません。代わりに、標準化された警告メッセージが表示されます。次に例を示します。
window.onbeforeunload = function () { return false; };
ユーザーがページから離れようとすると、このイベントにより確認ダイアログがトリガーされ、ページから離れるか、ページにとどまるかを確認するように求められます。
セキュリティとユーザーエクスペリエンスの懸念から、ブラウザはほとんどのカスタムメッセージを無視し、代わりに一般的なダイアログを表示します。beforeunload
を過度に使用すると、ユーザーエクスペリエンスが低下する可能性があるため、保存されていないデータの場合など、絶対に必要の場合にのみ使用する必要があります。
unloadイベント
unload
イベントは、ページが完全にアンロードされたときにトリガーされます(たとえば、ページが閉じられたり、更新されたり、移動されたりした場合)。beforeunload
とは異なり、unload
イベントはユーザーがページから離れるのを防ぐことはできません。これは主に、一時データのクリア、非同期リクエストのキャンセル、メモリの解放などの最終的なクリーンアップタスクを実行するために使用されます。
unload
イベントは、beforeunload
とは異なり、ユーザーにプロンプトを表示できません。代わりに、WebSocket接続のクローズ、ローカルストレージへのデータの保存、タイマーのクリアなどの操作に使用されます。
unload
イベントの特定のアプリケーションの1つは、ページがアンロードされる前に分析データを送信することです。navigator.sendBeacon(url, data)
メソッドを使用して、ページのアンロードを遅延させることなく、バックグラウンドでデータを送信できます。次に例を示します。
const analyticsData = { // 収集されたデータを含むオブジェクト }; window.addEventListener('unload', function () { navigator.sendBeacon('/analytics', JSON.stringify(analyticsData)); });
sendBeacon
リクエストが完了すると、ブラウザはドキュメントから既に離れている可能性があるため、サーバー応答を取得できません(応答は分析目的でしばしば空です)。
まとめ
HTML解析はページライフサイクルの基礎を形成しますが、それ自体はJavaScriptでリッスン可能なライフサイクルイベントではありません。DOMContentLoaded
イベントは、DOMツリーが完全に構築されるとトリガーされ、load
イベントは、ページ上のすべてのリソースが完全にロードされた後に発生します。beforeunload
イベントは、ユーザーにページからの移動を確認するように求め、unload
イベントは、ページのアンロード中にリソースのクリーンアップに使用されます。これらのイベントにより、開発者はページのロードおよびアンロードプロセスを制御し、ユーザーエクスペリエンスとページパフォーマンスを向上させることができます。
LeapcellはNode.jsプロジェクトをホストするための最適な選択肢です。
Leapcellは、ウェブホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです。
多言語サポート
- Node.js、Python、Go、またはRustで開発します。
無料で無制限のプロジェクトをデプロイ
- 使用量に対してのみ支払い - リクエストなし、料金なし。
比類のない費用対効果
- アイドル料金なしの従量課金制。
- 例:25ドルで平均応答時間60msで694万のリクエストをサポートします。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的なUI。
- 完全に自動化されたCI / CDパイプラインとGitOps統合。
- 実用的な洞察のためのリアルタイムのメトリクスとロギング。
簡単なスケーラビリティと高いパフォーマンス
- 高並行性を簡単に処理するための自動スケーリング。
- 運用上のオーバーヘッドゼロ - 構築に集中するだけです。
ドキュメントで詳細をご覧ください!
Xでフォローしてください:@LeapcellHQ