読み込み中...

JavaScriptのonloadで遅延が発生する原因と対策方法7選

JavaScriptのonloadイベントで遅延が発生する場合の対処法 JS
この記事は約13分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●onloadイベントとは?

Webページを開くとき、ブラウザはHTMLファイルをダウンロードし、そこに含まれるCSSやJavaScriptなどのリソースを読み込みます。

このとき、ページの読み込みが完了した時点で発火するのがonloadイベントです。

○onloadイベントの仕組み

onloadイベントは、window オブジェクトや XMLHttpRequest オブジェクトなど、さまざまなオブジェクトで利用できるイベントです。

最もよく使われるのが、windowオブジェクトのonloadイベントでしょう。

windowオブジェクトのonloadイベントは、ページ内のすべてのリソース(画像、スタイルシート、スクリプトなど)の読み込みが完了した時点で発火します。

つまり、DOMの構築が完了し、外部リソースもすべて読み込まれた状態になったタイミングで、onload イベントのイベントハンドラが実行されるわけです。

○サンプルコード1:基本的なonloadの使い方

それでは実際に、onloadイベントの基本的な使い方を見ていきましょう。

次のようなJavaScriptコードを考えてみます。

window.onload = function() {
  console.log("ページの読み込みが完了しました!");
};

このコードでは、window オブジェクトの onload プロパティに、無名関数を代入しています。

こうすることで、ページの読み込みが完了したタイミングで、コンソールに「ページの読み込みが完了しました!」というメッセージが出力されます。

実行結果

ページの読み込みが完了しました!

このように、onloadイベントを使えば、ページの読み込みが完了したタイミングで何らかの処理を実行することができます。

ただ、onloadイベントのイベントハンドラ内で重い処理を行うと、ページの表示が遅くなってしまう可能性があります。

そのため、onloadイベントは適切に使いわけることが大切ですね。

次は、onloadイベントで遅延が発生するケースを具体的に見ていきましょう。

●onloadイベントで遅延が発生する原因

JavaScriptのonloadイベントは便利な機能ですが、時として思わぬ遅延を引き起こすことがあります。

その原因を知っておくことは、Webパフォーマンスの最適化において非常に重要だと考えています。

○同期的な処理の実行

onloadイベントのイベントハンドラ内で、同期的に重い処理を行うと、ページの表示が遅くなってしまいます。

なぜなら、JavaScriptは単一スレッドで動作するため、ある処理が完了するまで次の処理が実行されないからです。

○サンプルコード2:同期的な処理の例

例えば、onloadイベント内で大量のデータを処理するような場合、ページの表示が遅くなる可能性があります。

window.onload = function() {
  // 大量のデータを処理する
  for (let i = 0; i < 1000000; i++) {
    console.log(i);
  }
};

このコードでは、onloadイベント内で100万回のループ処理を行っています。

実行すると、ページの表示が完了するまでに時間がかかってしまうでしょう。

○大量のデータ読み込み

onloadイベント内で、サーバーから大量のデータを読み込むような処理を行うと、ネットワークのレイテンシによって遅延が発生することがあります。

例えば、JSONファイルを読み込んでデータバインディングを行うような場合です。

○サンプルコード3:大量データ読み込みの例

次のコードは、onloadイベント内で大量のデータを読み込む例です。

window.onload = function() {
  // 大量のデータを読み込む
  fetch('https://example.com/large-data.json')
    .then(response => response.json())
    .then(data => {
      // 取得したデータを処理する
      console.log(data);
    });
};

このコードでは、fetch関数を使ってサーバーから大量のJSONデータを読み込んでいます。

データ量が多い場合、ネットワークのレイテンシによって遅延が発生する可能性があります。

○ネットワーク遅延の影響

onloadイベントの発火は、ページ内のすべてのリソースがダウンロードされた後に行われます。

そのため、ネットワークの遅延によってリソースのダウンロードに時間がかかると、onloadイベントの発火も遅くなってしまいます。

特に、モバイルネットワークでは、通信速度が不安定なことがあるため、注意が必要です。

リソースの数を減らしたり、サイズを小さくしたりするなど、ネットワークの負荷を軽減する工夫が求められるでしょう。

●onload遅延の対策方法

onloadイベントの遅延は、Webサイトのパフォーマンスに大きな影響を与えます。

ユーザー体験の向上とサイトの成功のためには、遅延を最小限に抑える工夫が欠かせません。

ここでは、onload遅延の対策方法について詳しく解説していきましょう。

○非同期処理の活用

onloadイベント内で行う処理を非同期化することで、ページの表示を高速化できます。

JavaScriptでは、非同期処理を実現するためのAPIとして、Promiseasync/awaitが用意されています。

これを活用することで、重い処理をバックグラウンドで実行し、ページのレンダリングをブロックせずに済むでしょう。

○サンプルコード4:非同期処理への変更例

先ほどの同期的な処理の例を、非同期処理を使って書き換えてみましょう。

window.onload = async function() {
  // 大量のデータを非同期で処理する
  const data = await new Promise(resolve => {
    setTimeout(() => {
      const result = [];
      for (let i = 0; i < 1000000; i++) {
        result.push(i);
      }
      resolve(result);
    }, 0);
  });

  console.log(data);
};

このコードでは、Promiseasync/awaitを使って、100万回のループ処理を非同期で実行しています。

setTimeoutを使ってタスクをイベントループに登録することで、メインスレッドをブロックせずに処理を進められます。

これにより、ページの表示が遅れることなく、重い処理を行えるようになるわけです。

○遅延ロードの実装

ページ内のすべてのリソースを一度に読み込もうとすると、onloadイベントの遅延につながってしまいます。

そこで、初期表示に必要なリソースのみを先に読み込み、それ以外は遅延ロードする方法が有効です。

JavaScriptを使えば、遅延ロードを柔軟に実装できるでしょう。

○サンプルコード5:遅延ロードの実装例

画像の遅延ロードを実装してみましょう。

<img data-src="image.jpg" alt="サンプル画像">

<script>
  window.onload = function() {
    const images = document.querySelectorAll('img[data-src]');

    images.forEach(img => {
      img.setAttribute('src', img.getAttribute('data-src'));
      img.onload = function() {
        img.removeAttribute('data-src');
      };
    });
  };
</script>

このコードでは、data-src属性に画像のURLを指定し、src属性は初期状態で空にしておきます。

onloadイベント内で、data-src属性を持つimg要素を取得し、src属性にdata-srcの値を設定することで、画像を遅延ロードしています。

こうすることで、初期表示に不要な画像の読み込みを後回しにでき、ページの表示速度を改善できるのです。

○不要なリソース読み込みの削減

Webページには、初期表示に不要なリソースが含まれていることがあります。

それらを削減することで、onloadイベントの遅延を防げます。

具体的には、未使用のJavaScriptライブラリや、不要なCSSファイル、大きすぎる画像などを取り除くことが重要です。

○サンプルコード6:不要リソース削減の例

例えば、jQueryを使わずにバニラJavaScriptで書き換えることで、外部ライブラリの読み込みを削減できます。

// jQueryを使った場合
$('.button').on('click', function() {
  // ボタンクリック時の処理
});

// バニラJavaScriptで書き換えた場合
document.querySelector('.button').addEventListener('click', function() {
  // ボタンクリック時の処理
});

このように、ネイティブのJavaScriptメソッドを使うことで、jQueryへの依存を取り除けます。

外部ライブラリを減らすことで、読み込むリソース数を最小限に抑えられるでしょう。

○CDNの活用

CDN(Content Delivery Network)を活用することで、リソースの読み込み速度を改善できます。

CDNは、世界中に分散されたサーバーネットワークを使って、ユーザーに近い場所からコンテンツを配信します。

これにより、レイテンシを低減し、onloadイベントの遅延を防ぐことができるのです。

○サンプルコード7:CDNの利用例

例えば、jQueryをCDNから読み込む場合は、次のようにします。

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

このコードでは、jQueryの公式CDNを使って、最新のバージョンのjQueryを読み込んでいます。

CDNを使うことで、ユーザーに近いサーバーからjQueryを配信できるため、読み込み速度が向上するわけです。

また、CDNのサーバーでキャッシュされたリソースを利用できるため、二度目以降のアクセスではさらに高速化が期待できます。

●onloadイベントのベストプラクティス

onloadイベントを使う際は、単に遅延対策を行うだけでなく、ベストプラクティスに従ってコードを最適化することが重要だと考えています。

ここでは、パフォーマンスを最大限に引き出すためのテクニックを見ていきましょう。

○コード分割と最適化

大規模なJavaScriptアプリケーションでは、コードを小さなモジュールに分割することが有効です。

これにより、必要なモジュールだけを遅延ロードできるため、初期ロードのパフォーマンスが改善されるでしょう。

また、デッドコードの削除やコード圧縮といった最適化手法を適用することで、ファイルサイズを削減し、読み込み速度を向上させることができます。

例えば、Webpackなどのモジュールバンドラーを使えば、コード分割と最適化を自動化できます。

// math.js
export function add(a, b) {
  return a + b;
}

// main.js
import { add } from './math.js';

console.log(add(1, 2));

上記のように、math.jsで定義したadd関数をmain.jsでインポートしています。

Webpackを使ってビルドすれば、必要なモジュールだけが1つのファイルにバンドルされ、不要なコードが削除された最適化済みのJavaScriptファイルが出力されます。

このようにコードを分割・最適化することで、onloadイベント発火までの時間を短縮できるのです。

○プログレッシブレンダリングの活用

プログレッシブレンダリングとは、ページの一部を先に表示し、残りは後からロードする手法です。

これにより、ユーザーはコンテンツを早く見ることができ、待ち時間のストレスを感じにくくなります。

onloadイベントが完了するまで何も表示されないのではなく、段階的にコンテンツを表示していくことで、ユーザー体験を向上させられるでしょう。

プログレッシブレンダリングを実現する方法の1つが、スケルトンスクリーンです。

これは、コンテンツの読み込み中に、コンテンツの構造を表す骨組みを表示するものです。

<div class="skeleton">
  <div class="skeleton-header"></div>
  <div class="skeleton-content"></div>
  <div class="skeleton-footer"></div>
</div>

<style>
.skeleton {
  background-color: #f0f0f0;
}

.skeleton-header {
  width: 100%;
  height: 50px;
  background-color: #ddd;
}

.skeleton-content {
  width: 100%;
  height: 200px;
  background-color: #ddd;
  margin-top: 10px;
}

.skeleton-footer {
  width: 100%;
  height: 30px;
  background-color: #ddd;
  margin-top: 10px;
}
</style>

このようなHTMLとCSSを用意しておき、コンテンツの読み込みが完了したらスケルトンスクリーンを非表示にすることで、プログレッシブレンダリングを実装できます。

ユーザーはスケルトンスクリーンを見ることで、コンテンツがロードされていることを認識でき、スムーズにコンテンツを閲覧できるようになるわけです。

○パフォーマンス計測と改善

onloadイベントの遅延を改善するには、まずパフォーマンスを計測し、ボトルネックを特定することが大切です。

DevToolsのPerformanceタブを使えば、ページのロードにかかった時間や、各リソースのダウンロード時間などを詳細に分析できます。

また、Lighthouseを使ってWebサイトのパフォーマンスを自動で診断し、改善点を洗い出すこともできるでしょう。

$ lighthouse https://example.com --view

このコマンドを実行すると、Lighthouseがさまざまな観点からサイトを分析し、パフォーマンススコアとともに改善のためのアドバイスを提示してくれます。

これを参考にしながら、onloadイベントの遅延を引き起こしている要因を1つずつ取り除いていくことで、着実にパフォーマンスを向上させていけるはずです。

まとめ

本記事では、onloadイベントの仕組みや基本的な使い方から、遅延が発生する原因と対策方法までを詳しく解説してきました。

パフォーマンスの改善には、地道な計測と分析の繰り返しが欠かせません。

一朝一夕にはいかないかもしれませんが、本記事で紹介した内容を手がかりに、着実にスキルを高めていってください。

そして、開発者としてのレベルアップを図り、プロジェクトの成功に貢献できるエンジニアを目指してほしいと思います。