SvelteとIntersection Oberverによるレイジーローディング

出版日: 2024年5月10日

SvelteとIntersection Oberverによるレイジーローディング

ウェブサイトで多くのコンテンツを提供していると想像してみてください。以下のような高品質の画像がたくさんあるとします。

すべての画像を見るにはスクロールしてください

画像 画像 画像 画像 画像 画像 画像 画像 画像 画像 画像 画像

上記の画像は合計で10MB以上になります!このような大量のデータを読み込むことは、特にデータ量が少ない環境のユーザーにとって、ユーザーインターフェイスに摩擦を引き起こすでしょう。

Svelteは、WebPなどの形式で画像を提供するのに役立つenhanced:imgなどのツールを提供しています。

ただし、画像が大きすぎる場合、この解決策では完全な回避策を提供できません。ここでlazy loadingが登場します。

レイジーローディング (Lazy Loading・遅延読み込み)

遅延読み込みのアイデアは、ユーザーがそれにスクロールするまでコンテンツの読み込みを待つというものです。

この方法で、最初にビューポート内に見えるコンテンツのみを読み込み、他のコンテンツの読み込みを保留にすることができます。これにより、読み込み時間が大幅に短縮されます。

このアイデアは、以下のようにSvelteで実装できます。

{#each images as image}
 {#if scrolledToImage}
  <img src={image} />
 {/if}
{/each}

ユーザーエクスペリエンスを向上させるために、フェードインのトランジションを追加することができます。これにより、ユーザーがスクロールすると画像が読み込まれているように見えますが、実際にはその通りです。

<script>
import { fade } from 'svelte/transition';
let images = [img1, img2, img3, ...]
let scrolls = [scrollForImg1, scrollForImg2, scrollForImg3, ...]
</script>
 
{#each images as image, index}
 {#if scrolls[index]}
  <div transition:fade={{ duration: 300 }}>
   <img src={image} />
  </div>
 {/if}
{/each}

Svelteでトランジションを動作させるには、DOMに入る必要があり、それがifステートメントで私たちを助けるところです。

ステートメントは遅延読み込みの骨格でもあり、スクロールされない要素はレンダリングされないため、リソースを節約します。

では、ユーザーが対象の画像までスクロールしたかどうかをどのように判断するかを見てみましょう。scrolledToImage。これは、 Intersection Observer API を使用します。

Intersection Observer

詳細には触れませんが、上記のリンクに詳細がありますが、Intersection Observerは、1つのアイテムが別のアイテムと交差するとイベントが発生します。たとえば、viewportを基本アイテムとして使用すると、交差とはアイテムがスクロールされているかどうかを意味します。

構文は次のようになります:

let callback = (entries, observer) => {
 entries.forEach((entry) => {
  if (entry.isIntersecting) {
   // load image
  }
 });
};

let observer = new IntersectionObserver(callback, { threshold: 0 }); 
// threshold:0 means any part of item is intersecting the viewport. I.e. the view is scrolled to.
 
observer.observe(element);

IntersectionObserverは、Svelteでコンポーネントがマウントされた後に呼び出される必要があります。なぜなら、このオブジェクトはサーバーに存在せず、エラーが発生するためです。

すべてを結びつける

<script>
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';

// Array that will keep the image divs
let divs = images.map(() => null);

// Array that will keep info about whether an image is scrolled to
let scrolls = images.map(() => false);

// Setup intersection observer when component is mounted 
onMount(async () => {
 let callback = (entries, observer) => {
  entries.forEach((entry) => {
   if (entry.isIntersecting) {
    // we get the div id, which will point us to the right element in scrolls array
    scrolls[entry.target.id] = true;
   }
  });
 };

 // Set the rooter as the div with id "container" as that is the parent div of the images
 let observer = new IntersectionObserver(callback, { threshold: 0, root: document.querySelector('#container') });

 // Observe each div
 divs.forEach((d) => {observer.observe(d)});
});
</script>

// NOTE1: the parent div of each image needs to have an initial height. (E.g. 300px)
// Otherwise, they will be defaulted to 0 at first,
// and all images will be intersecting with the container.
// This will load all images at once, which will defy our purpose.

// NOTE2: transition:fade should NOT be dded to img element
// Instead, add an enclosing div, and add it to that div
// Otherwise, transitions don't work on image elements.

<div id="container">
 {#each images as image, index}
  <div bind:this={divs[index]} id={index} class="min-h-[300px]">
   {#if scrolls[index]}
    <div transition:fade={{ duration: 500 }}>
     <img src={image} class="h-[300px] object-contain" alt="An object" />
    </div>
   {/if}
  </div>
 {/each}
</div>

では、上記のコードが上記で見たコンテナで機能するかどうかを確認しましょう。

すべての画像を見るにはスクロールしてください

できました!見栄えがしますね。今や、SvelteのトランジションとIntersection Observerのパワーを使って、ファンシーな遅延読み込みを作成できます。

上記のコードが本当に遅延読み込みされているかどうかを確認してみましょう:

遅延読み込みのテスト

Chromeの開発者ツールで、コンテナがスクロールされていない(つまり、デフォルトのスクロール位置にある)場合、2つのdivにだけ画像が含まれていることがわかります。残りのdivには画像が含まれていません。

したがって、最初に2つの画像のみを読み込みました。ユーザーがスクロールしない場合、それで終わりです。ユーザーがスクロールすることを決めた場合、ユーザーがスクロールすると読み込みます。これは、ユーザー中心のリソース節約型のコンテンツ提供アプローチです。

まとめ

この記事を読んだ後に、SvelteのトランジションとIntersection Observerを使用して遅延読み込みを実装できると良いですね。進捗状況を教えてください!

楽しいハッキングを!

このブログは英語からChatGPTによって翻訳されました。不明な点がある場合は、お問い合わせページからご連絡ください。

コメントを残す

コメント

その他のブログ

SvelteとJavaScriptを使用してシンプルで動的なツールチップを作成する

2024/06/19

SvelteとJavaScriptを使用してシンプルで動的なツールチップを作成する

JavaScriptSvelteTooltip動的シンプルツールチップフロントエンド
JavaScriptを用いて東京都のインタラクティブな地図を作成する

2024/06/17

JavaScriptを用いて東京都のインタラクティブな地図を作成する

SvelteSVGJavaScriptTailwindインタラクティブな地図東京市区町村23区地図
Matplotlibで日本語文字化けを解決できる簡単な方法

2024/06/14

Matplotlibで日本語文字化けを解決できる簡単な方法

MatplotlibグラフチャートPython日本語文字化け問題バグ
書評 | トーキング・トゥ・ストレンジャーズ 「よく知らない人」について私たちが知っておくべきこと by マルコム・グラッドウェル

2024/06/13

書評 | トーキング・トゥ・ストレンジャーズ 「よく知らない人」について私たちが知っておくべきこと by マルコム・グラッドウェル

書評トーキング・トゥ・ストレンジャーズ「よく知らない人」について私たちが知っておくべきことマルコム・グラッドウェル
日本語で最もよく使われる3000字の漢字

2024/06/07

日本語で最もよく使われる3000字の漢字

3000よく使う準漢字使用回数漢字日本語漢字リスト漢字普及率日本語能力試験独学勉強単語
VSCodeでRegexを使用してReplaceする方法

2024/06/07

VSCodeでRegexを使用してReplaceする方法

VSCodeRegex検索置き換える条件付き置換FindReplaceConditional Replace
SvelteではReadable Storeを使用するな

2024/06/06

SvelteではReadable Storeを使用するな

SvelteReadableWritableステート管理ストアStore速度メモリファイルサイズ
GzipとPakoでデータを圧縮してWebサイトのローディング速度を上げる方法

2024/06/05

GzipとPakoでデータを圧縮してWebサイトのローディング速度を上げる方法

Gzip圧縮PakoWebサイトローディング速度SvelteKit
JavaScriptを使用してWebページ上でマウスが指している単語を特定する

2024/05/31

JavaScriptを使用してWebページ上でマウスが指している単語を特定する

JavascriptマウスPointerHoverWeb開発
SvelteとSVGを用いてインタラクティブな地図を作成する

2024/05/29

SvelteとSVGを用いてインタラクティブな地図を作成する

SvelteSVGインタラクティブな地図フロントエンド
書評 | Originals 誰もが「人と違うこと」ができる時代 by アダム・グラント & シェリル・サンドバーグ

2024/05/28

書評 | Originals 誰もが「人と違うこと」ができる時代 by アダム・グラント & シェリル・サンドバーグ

書評Originals誰もが「人と違うこと」ができる時代アダム・グラント & シェリル・サンドバーグ
Javascriptを使用して数独を解く方法

2024/05/27

Javascriptを使用して数独を解く方法

数独を解くアルゴリズムJavaScriptコーディング
ウェブサイトへのトラフィックを1か月で10倍に増やした方法

2024/05/26

ウェブサイトへのトラフィックを1か月で10倍に増やした方法

ウェブサイトへのトラフィック増加クリックインプレッションGoogle Search Console
人生はサイクリングに似ている

2024/05/24

人生はサイクリングに似ている

サイクリング人生哲学成功
JavaScriptでバックトラッキング・アルゴリズムを用いて完全な数独グリッドを生成する

2024/05/19

JavaScriptでバックトラッキング・アルゴリズムを用いて完全な数独グリッドを生成する

数独バックトラッキング・アルゴリズム完全なグリッドJavaScript
Tailwindが素晴らしい理由とWeb開発をいかに楽にするか

2024/05/16

Tailwindが素晴らしい理由とWeb開発をいかに楽にするか

Tailwind素晴らしいフロントエンドWeb開発
PythonとGitフックを使用してサイトマップを自動的に生成する

2024/05/15

PythonとGitフックを使用してサイトマップを自動的に生成する

GitフックPythonサイトマップSvelteKit
書評 | Range (レンジ) 知識の「幅」が最強の武器になる by デイビッド・エプスタイン

2024/05/14

書評 | Range (レンジ) 知識の「幅」が最強の武器になる by デイビッド・エプスタイン

書評Range (レンジ)David Epstein (デイビッド・エプスタイン)知識の「幅」が最強の武器になる
SvelteとSvelteKitはなんですか?

2024/05/13

SvelteとSvelteKitはなんですか?

SvelteSvelteKitFront-endVite
SvelteKitで国際化(多言語化)

2024/05/12

SvelteKitで国際化(多言語化)

国際化多言語SvelteKitI18N
SvelteでCachingを用いてDeploy時間を短縮する方法

2024/05/11

SvelteでCachingを用いてDeploy時間を短縮する方法

SvelteEnhanced ImageCachingDeploy Time
遺伝的アルゴリズムで最適な株式ポートフォリオを作る方法

2024/05/10

遺伝的アルゴリズムで最適な株式ポートフォリオを作る方法

株式書状ポートフォリ最適化遺伝的アルゴリズムPython
Pythonを用いてShapeFileをSVGに変換できる方法

2024/05/09

Pythonを用いてShapeFileをSVGに変換できる方法

ShapeFileSVGPythonGeoJSON
Svelteの反応性:変数、バインディング、およびキー関数

2024/05/08

Svelteの反応性:変数、バインディング、およびキー関数

Svelte反応性バインディングキー関数
書評 | 孫子の兵法

2024/05/07

書評 | 孫子の兵法

書評The Art Of War (兵法)Sun Tzu (孫子)Thomas Cleary
スペシャリストは終了。ゼネラリスト万歳!

2024/05/06

スペシャリストは終了。ゼネラリスト万歳!

専門家ジェネラリストパラダイムシフトソフトウエア・エンジニアリング
トルコ人の有権者の投票行動をPythonでの分析

2024/05/03

トルコ人の有権者の投票行動をPythonでの分析

トルコ投票者年齢分析国家投票有権者行動分析
Seleniumを用いてトルコ投票データベースを作る方法

2024/05/01

Seleniumを用いてトルコ投票データベースを作る方法

PythonSeleniumWeb Scrapingトルコ国家投票
SvelteとTailwindを使用してInfinite Scrollできる方法

2024/04/30

SvelteとTailwindを使用してInfinite Scrollできる方法

SvelteTailwindInfinite ScrollFront-end
1年間以内で日本語を駆使できるようになるための方法

2024/04/29

1年間以内で日本語を駆使できるようになるための方法

日本語短時間言語学習日本語能力試験ビジネス日本語
SvelteとTailwindを用いたWebサイトテンプレート

2024/04/25

SvelteとTailwindを用いたWebサイトテンプレート

Web開発フロントエンドSvelteTailwind
怠惰なエンジニアとひどいデザイン

2024/01/29

怠惰なエンジニアとひどいデザイン

怠け者エンジニア質の悪い製品StarbucksSBI証券
偉大さについて

2024/01/28

偉大さについて

雄大さ人生の意味満足できる人生目的
MacBook で PDF を PNG に変換する

2024/01/28

MacBook で PDF を PNG に変換する

PDFPNGMacBookAutomator
2023年振り返り:24冊の読んだ本のまとめ

2023/12/31

2023年振り返り:24冊の読んだ本のまとめ

読書 2023振り返り
Python PILを使用して写真コラージュを作成する方法

2023/12/30

Python PILを使用して写真コラージュを作成する方法

PythonPIL画像処理コラージュ
ウェブサイトの訪問者のデバイスとブラウザを検出する方法

2024/01/09

ウェブサイトの訪問者のデバイスとブラウザを検出する方法

Javascript端末検知ブラウザ検知Website分析
ChatGPT回答の解析

2024/01/19

ChatGPT回答の解析

ChatGPT大規模言語モデル機械学習生成AI