2021年5月1日土曜日

picture/source/srcset な WebP を力技で polyfill

iOS 14 で WebP がサポートされたので、webp-hero で IE のために polyfill した上で、いくつかのサイトを完全に WebP 化してみました。 しかし webp-hero は picture/source/srcset に対応していないので、iOS 14 以下で WebP が表示されないという問題が起きてしまいました。 IE はともかく古めの iPad / iPhone を使っている人はそれなりに居るのでこれはマズイ。



遊んでみたところ、webp-hero の picture/source/srcset の polyfill 問題は、以下のように解決できるとわかりました。 荒業ですが、picture/source/srcset を削除します。 私は picture/source/srcset を通信量削減のために使うことが多いので、古い OS の表示が遅くなることになります。 とはいえ指定の仕方を統一しておけば影響も小さいので、別に良いかなと。 この適当 polyfill を入れておけば、IE を含めた古めの iOS サポートも安心です。
<picture>
  <source srcset="/img/test.webp" media="(min-width: 768px)">
  <img src="/img/test-small.webp" alt="test"
    class="img-fluid" loading="lazy" width="300" height="225">
</picture>
<img src="/img/test.webp" alt="test" width="600" height="450"
  srcset="/img/test-small.webp 300w,/img/test.webp 600w"
  sizes="(max-width: 768px) 300px,600px"
  class="img-fluid" loading="lazy">

<script>
  // picture/source 要素で指定している場合はこちら
  function removePicture() {
    const imgs = document.querySelectorAll('picture > img');
    for (let i=0; i<imgs.length; i++) {
      const picture = imgs[i].parentNode;
      picture.parentNode.insertBefore(imgs[i], picture);
      picture.parentNode.removeChild(picture);
    }
  }

  // srcset 属性で指定している場合はこちら
  function removeSrcset() {
    const imgs = document.querySelectorAll('img[srcset]');
    for (let i=0; i<imgs.length; i++) {
      imgs[i].removeAttribute('srcset');
    }
  }

  var webpMachine = new webpHero.WebpMachine();
  webpMachine.webpSupport.then(function(support) {
    if (!support) {
      removeSrcset();
      removePicture();
      webpMachine.polyfillDocument();
    }
  });
</script>
これにて PNG/JPEG とはおさらばです。 小さな画像だとたまに PNG/JPG のほうが圧縮率が高いこともあるのですが、面倒だから WebP で良いかなという気もしてます。

0 件のコメント: