众所周知、パフォーマンスの最適化には通常、2 つの要素があります。それは、読み込まないこととキャッシュです。
もちろん、読み込まないことはできませんので、今日は遅延読み込みについて説明します。
現在のウェブページでは、大量の JavaScript の読み込み以外にも、最適化できる箇所があります。
フォントファイルの読み込みに関しては、私の記事「フォントモジュールの設計」をご覧ください。
画像の読み込み#
画像のパフォーマンス最適化には、圧縮、フォーマット、GIF の代わりに動画を使用する、サイズに基づいた画像の提供、WebP の使用、CDN の使用など、多くの要素が含まれます。これらは今日のトピックではありませんが、今日は画像の遅延読み込みについて見ていきます。
最新のブラウザでは、デフォルトでブラウザレベルの遅延読み込みが実装されており、loading 属性を使用して有効にすることができます。
<img loading="lazy" />
また、IntersectionObserver オブジェクトを使用して、より細かい制御で画像の遅延読み込みを開始することもできます。例えば、ビューポートに表示されてから 1 秒以上経過した場合にのみ画像を表示するなどです。
// 遅延読み込みするすべての画像要素を取得
const lazyImages = document.querySelectorAll(".lazy-loaded-image");
// IntersectionObserverのオプションを設定
const options = {
root: null,
rootMargin: "0px",
threshold: 0.5
};
// IntersectionObserverオブジェクトを作成
const lazyImageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
// 画像がビューポートに表示されてから1秒以上経過した場合、画像を読み込む
setTimeout(() => {
const lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}, 1000);
}
});
}, options);
// 遅延読み込みするすべての画像要素を監視
lazyImages.forEach((lazyImage) => {
lazyImageObserver.observe(lazyImage);
});
CSS ファイル内の画像#
CSS ファイル内の画像は、上記の方法では読み込むことができませんが、同様にビューポートの監視を使用して、クラス名を動的に追加することで遅延読み込みを実現することができます。
.lazy-background {
background-image: url("hero-placeholder.jpg");
/* プレースホルダー画像 */
}
.lazy-background.visible {
background-image: url("hero.jpg");
/* 実際の画像 */
}
上記のコードを変更して、setTimeout の中身を以下のように置き換えることで、CSS での画像読み込み方法を動的に変更し、遅延読み込みを実現することができます。
lazyBackGround.classList.add("visible");
動画の遅延読み込み#
video 要素には lazy 属性はありませんが、preload 属性を使用することができます。
<video controls preload="none" poster="one-does-not-simply-placeholder.jpg">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
ここで、poster 属性は非常に便利で、画像をプレースホルダーとして使用することができます。
先ほども述べたように、GIF の代わりに動画を使用することができます。これは、同じコンテンツでも、動画は明らかな容量の利点があるためです。
このような場合、video タグは次のようになります。
<video class="lazy" autoplay muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
<source data-src="one-does-not-simply.webm" type="video/webm">
<source data-src="one-does-not-simply.mp4" type="video/mp4">
</video>
IntersectionObserver を使用して、source 要素の src を動的に置換することで、遅延読み込みを細かく制御することもできます。
if (video.isIntersecting) {
for (var source in video.target.children) {
var videoSource = video.target.children[source];
if (typeof videoSource.tagName === 'string' && videoSource.tagName === 'SOURCE') {
videoSource.src = videoSource.dataset.src;
}
}
video.target.load();
video.target.classList.remove('lazy');
lazyVideoObserver.unobserve(video.target);
}
iframe の遅延読み込み#
iframe も同様に loading=lazy をサポートしています。最も簡単な方法は、直接タグに追加することです。これは、多くのビデオが埋め込まれているページの場合に非常に効果的です。