IntersectionObserver(feat.React)の使用


IntersectionObserverの使い方が分かった以上、今は正式にウェブサイトに応用しなければなりません.

問題の状況



これはlazy loadingを適用する前のサイトの様子です.極端な例のために、ネットワークの状況をFast 3 Gに設定します.
Webページをロードすると、ページ上のすべての画像ファイルをダウンロードし、順番に表示されることを確認できます.

IntersectionObserverの使用


ページ内のすべての画像ファイルでIntersectionObserverを使用するには、各画像にObserverをアタッチし、IntersectionObserverを実行します.
<img src={props.presrc} alt={props.label+' 이미지'} className="cards__item__img" data-lazy={props.src}/>
画像ラベルは以下のように設定されています.srcプロパティはプレースホルダ画像を指定し、実際に表示される画像はdata-lazyプロパティに指定します.
const images = document.querySelectorAll("img");

const observer = new IntersectionObserver((entries, observer) => {
    entries.forEach((entry) => {
        if (!entry.isIntersecting) return;
        const image = entry.target;
        const src = image.getAttribute("data-lazy");
        image.setAttribute("src", src);
        observer.unobserve(image);
      })

images.forEach((image) => {
    observer.observe(image);
})
前述したように、すべての画像に1人の観察者を追加し、isIntersection法により画像のsrc属性を変更します.

React Routerでの使用


ここで追加の問題が発生したのはreactrouterのためです.routerを使用して各ページを実装しましたが、このページのリフレッシュ中に画像をロードできないという問題が発生しました.
当初、window.addEventListener('load', ~~)によってこのイベントを解決しようとしたが、このイベントは最初は実行時に発生した.すなわち、App.jsは最初は実行時に発生しただけで、ルータページでどのようにリフレッシュしても解決できなかった.
Lazy loadingを適用せずにWebPイメージを直接使用して最適化することを考慮すると、class Componentを使用すべきだとふと思いました.(本当に稲妻のようにふと思い出した)
既存の構造
App
| - Bread (빵 목록 보여주는 페이지)
|   | - BreadList (실제 빵 종류들)
|   | - Footer
| - Vegetable
|   | - VegetableList
|   | - Footer
| - Cheese
|   | - CheeseList
|   | - Footer
| - Sauce
    | - SauceList
    | - Footer
以前は、上記の構造はすべてfunctioncomponentとして宣言されていました.ここで画像をレンダリングするファイルは~Listで、これらのファイルはclass componentです.
これにより、さまざまなライフサイクルメソッドが使用できます.実際に、リフレッシュしてもコンポーネントDidMountメソッドが呼び出されることを確認しました.
最終クラスコンポーネントのコードは、次のようになります.
class BreadList extends React.Component {
  // componentDidMount 내에 IntersectionObserver를 선언
  // 새로 고침 시에도 이 부분이 항상 실행됨. 문제 해결!
  componentDidMount() {
    const images = document.querySelectorAll("img");

    const observer = new IntersectionObserver((entries, observer) => {
      entries.forEach((entry) => {
        if (!entry.isIntersecting) return;
        const image = entry.target;
        const src = image.getAttribute("data-lazy");
        image.setAttribute("src", src);
        observer.unobserve(image);
      })
    })

    images.forEach((image) => {
      observer.observe(image);
    })
  }

  render() {
    return (
        <div>빵 목록들</div>
    )
  }
}

結果



以前とは異なり、画像はロード前にロードされた画像を表示し、スクロール時にのみ必要な追加画像が表示されます.また、イメージはリフレッシュ時に正常にロードされます.
内容は複雑ではありませんが、実際のサイトに適用するには、思ったより時間がかかります.それに反応物の特性も問題になっているので、解決策を探しています.
しかし、このように解決した後、私は今本当に私のものだと思います!😁