1. 導入:なぜライフサイクルイベントが重要なのか
Web開発において、JavaScriptを「どのタイミングで実行するか」を制御することは非常に重要です。DOMが構築される前に要素を操作しようとするとエラーが発生し、逆に画像や外部リソースのロードを待ちすぎるとユーザー体験(UX)が低下します。ページのライフサイクルイベントを正しく理解し、適切に使い分けることで、アプリケーションの安定性とパフォーマンスを向上させることができます。
2. 基礎知識:主要な4つのイベント
ブラウザがページを表示するまでの過程で、主に以下のイベントが発生します。
DOMContentLoaded: HTMLのパースが完了し、DOMツリーが構築された時点で発火します。画像や外部スタイルシートの読み込みは待たないため、UIの初期化などに最適です。
load: 画像やCSSを含む、ページ内のすべてのリソースが完全に読み込まれた後に発火します。
beforeunload: ユーザーがページを離れようとした際に発火します。フォームの未保存データがある場合などに警告を出すために使われます。
unload: ページが完全に閉じられる直前に発火します。
3. 実装と解決策:適切なイベントの選び方
基本的には、JavaScriptの実行は DOMContentLoaded を利用するのがベストプラクティスです。これにより、ユーザーはページが読み込まれた直後から操作を開始できます。
また、外部スクリプトを読み込む際は、defer 属性を使用することを強く推奨します。defer を使うと、DOMの構築をブロックせずにバックグラウンドで読み込まれ、DOM構築完了後に実行されるため、パフォーマンスを最大限に引き出すことができます。
4. サンプルプログラム
以下は、ライフサイクルイベントを適切に活用するための実用的なコード例です。
// DOMが準備できたタイミングで実行(高速なUI初期化)
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM構築完了。UIのイベントリスナーを設定します。');
const button = document.querySelector('#submit-btn');
button.disabled = false;
});
// すべてのリソース(画像など)がロードされた後に実行
window.addEventListener('load', () => {
console.log('ページ全体が読み込まれました。画像のサイズなども取得可能です。');
});
// ユーザーがページを離れようとした時の警告
window.addEventListener('beforeunload', (event) => {
// フォームの入力内容が残っている場合などの警告
event.preventDefault();
event.returnValue = ''; // ブラウザの標準ダイアログを表示
});
5. 応用・注意点:現場で陥りやすい罠
1. スタイルシートの待機に注意
DOMContentLoaded はスタイルシートの読み込みを待機しませんが、その直後に記述されたスクリプトはスタイルシートの読み込みを待ちます。そのため、CSSの適用結果(要素の幅や高さなど)に依存するロジックは、load イベントか、スタイルが確定した後に実行する設計が必要です。
2. readyStateの活用
ライブラリの読み込みタイミングによっては、既に DOMContentLoaded が発火した後にコードが実行される場合があります。そのような場合は、document.readyState を確認しましょう。
function initApp() {
console.log('アプリの初期化処理');
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initApp);
} else {
// すでに準備完了している場合は即座に実行
initApp();
}
3. asyncとdeferの使い分け
広告タグや解析ツールなど、DOMに依存しないスクリプトは async を、メインのアプリケーションロジックは defer を使用することで、ブラウザの自動入力(パスワード保存機能など)をブロックせずにスムーズな体験を提供できます。