JavaScript : 画像をwebPにしてウェブサイトの読み込みを早くする

JavaScript : 画像をwebPにしてウェブサイトの読み込みを早くする

2024年2月11日

ウェブサイトを作成する時にはページの読み込み速度にも気を使います。画像形式はjpgやpng,gifが主流ですが、webPにすることでファイルサイズを軽量化することができます。
ただ、気になるところは非対応のブラウザにはどうするのか?というところではないでしょうか。
大半のブラウザは対応していると思いますが、非対応のブラウザでも問題なく代替画像を読み込めるようにしておくのが良いかと思います。
下記はブラウザがWebPをサポートしている場合にはwebPを、非対応であればjpgやpng画像を読み込むためのスクリプトです。

HTMLで画像を指定する。

ブラウザがwebPに対応しているのかどうか、JavaScriptに対応しているかで読み込まれる画像が変わります。
data-src-webp=”test.webp”は、ブラウザがWebP画像形式をサポートしている場合に使用される画像のパスです。
data-src-fallback=”test.jpg”は、ブラウザがWebPをサポートしていない場合にフォールバックとして使用される画像のパスです。
src=”test.jpg”は、JavaScriptが実行される前や、もしJavaScriptが無効化されている場合に表示される初期画像のパスです。

<img src="test.jpg" data-src-webp="test.webp" data-src-fallback="test.jpg" alt="代替テキスト">

JavaScript

// WebP画像のサポートを検出する関数を定義します。
function supportsWebP(callback) {
  // 新しいImageオブジェクトを作成します。
  var image = new Image();
  
  // 画像が正常に読み込まれた場合のイベントハンドラを設定します。
  image.onload = function() {
    // 画像の幅と高さが0より大きい場合、WebPがサポートされていると判断します。
    var isSupported = (image.width > 0) && (image.height > 0);
    // コールバック関数を呼び出して、結果(trueまたはfalse)を渡します。
    callback(isSupported);
  };
  
  // 画像の読み込みに失敗した場合のイベントハンドラを設定します。
  image.onerror = function() {
    // コールバック関数を呼び出して、サポートされていないこと(false)を渡します。
    callback(false);
  };
  
  // WebP形式の画像データを含むData URLを設定します。
  // このData URLはWebPのサポートを検出するために使用されます。
  image.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
}

// supportsWebP関数を呼び出して、ブラウザがWebPをサポートしているかどうかを検出します。
supportsWebP(function(supported) {
  // ページ内のすべてのimg要素を選択します。これらの画像はdata-src-webp属性とdata-src-fallback属性を持っています。
  var images = document.querySelectorAll('img[data-src-webp]');
  
  // 選択した画像のそれぞれに対してループ処理を行います。
  for (var i = 0; i < images.length; i++) {
    if (supported) {
      // ブラウザがWebPをサポートしている場合、data-src-webp属性の値をsrc属性に設定します。
      images[i].src = images[i].getAttribute('data-src-webp');
    } else {
      // ブラウザがWebPをサポートしていない場合、data-src-fallback属性の値をsrc属性に設定します。
      images[i].src = images[i].getAttribute('data-src-fallback');
    }
  }
});

今あるimgタグを修正したくない場合

これまでの方法だとdata-src-webpやdata-src-fallbackなどを付けなくてはならないので、実はとても面倒です。
これまでどおりの指定で、webPの画像を指定するという書き方であれば下記のようにすればタグは特に何もせずにいけます。

document.addEventListener('DOMContentLoaded', function() {
    if (supportsWebP) {
        var images = document.getElementsByTagName('img');
        for (var i = 0; i < images.length; i++) {
            (function(image) {
                var originalSrc = image.getAttribute('src');
                var webpSrc = originalSrc.replace(/\.(jpg|jpeg|png)$/, '.webp');
                
                var testImage = new Image();
                testImage.onload = function() {
                    image.setAttribute('src', webpSrc);
                };
                testImage.onerror = function() {
                    // WebP画像の読み込みに失敗した場合、元の画像ソースを維持
                    image.setAttribute('src', originalSrc);
                };
                testImage.src = webpSrc;
            })(images[i]);
        }
    }
});

まとめ

既存サイトでjpgやpng画像が大量にある場合など、とりあえずHTMLなどのソースは書き直さずに対応したいという場合には良い方法だと思います。