為什麼要使用圖片 LazyLoad?

1. 減少頻寬浪費

圖片與影片是網站中最吃資源的元素之一,尤其在行動網路環境下,過度 PreLoad 預載會導致頻寬浪費。LazyLoad 可延遲非可視範圍內的圖片載入,只在使用者滑動到該區域時才載入圖片。

2. 提升首次載入速度

圖片載入不只是下載,還會耗用瀏覽器 CPU 解析與渲染時間。

LazyLoad 可避免瀏覽器在首次載入時就忙著處理整頁圖片,提升 First Paint 時間,讓內容更快顯示。

3. 強化使用者體驗

使用者更快看到畫面上可見的內容,自然會覺得「這網頁好快」。反之,如果等圖卡住了頁面,體驗就會大打折扣。

各大網站 LazyLoad 的應用範例

PChome


先顯示灰底圖片,等圖片載入後才替換。

ETtoday


有 loading 動畫的底圖,載入圖片後再替換。

Medium 的高級做法:漸進式圖片置換


Medium 的做法分成三階段:

  1. 灰色底圖
  2. 模糊縮圖(2.9kb)
  3. 高解析圖(375kb)

這段流程的視覺體驗非常順暢,也確保圖片漸進式地「漸入佳境」✨

開發者工具觀察:


Medium 不是單純地 src 替換,而是先加載一張模糊小圖,過渡到最終大圖。


LazyLoad 的實作方式

方法一:scroll 事件 + getBoundingClientRect

優點:

  • 古老萬用,IE 也支援

缺點:

  • 滾動監聽效能差,需自行計算進入視窗與否

方法二:IntersectionObserver API

優點:

  • 使用簡單,效能佳,不會造成瀏覽器 reflow。
  • 內建進入視窗可視範圍判斷

缺點:

  • IE 不支援(但有 polyfill)

這方法現在已是主流。

方法三:原生 loading="lazy" 屬性

<img src="image.jpg" loading="lazy" />

優點:

  • 無需 JS,超簡單

缺點:

  • Safari 直到近期才支援,IE 完全不支援

實作:打造一個 React LazyLoad 圖片元件

目標:模糊圖片過渡到清晰圖片

LazyImg 元件實作說明:

const LazyImg = ({ src, defaultImg, className, alt }) => {
  const ref = useRef(null);

  const loadImage = useCallback((img, observer) => {
    img.src = img.dataset.src;
    observer.unobserve(img);
  }, []);

  useEffect(() => {
    const observer = new IntersectionObserver((entries, obs) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          loadImage(entry.target, obs);
        }
      });
    });

    if (ref.current) observer.observe(ref.current);

    return () => observer.disconnect();
  }, [src]);

  return (
    <img
      ref={ref}
      data-src={src}
      src={defaultImg}
      alt={alt}
      className={className}
    />
  );
};

使用方式:

<LazyImg
  src="/final.jpg"
  defaultImg="/defaultImg.jpg"
  alt="final"
/>

我們假設:後端一開始資料就傳了預設圖或縮小圖 defaultImg.jpg 給我們,所以一開始預設圖片就先用 defaultImg.jpg。當透過 IntersectionObserver API 偵測到畫面進入可視範圍,就動態替換掉 defaultImg.jpg 改用 final.jpg。

什麼你說這樣網頁載入,一開始還是會有很多 defaultImg.jpg 的 request 請求?

我們可以全部的 <LazyImg/> 元件都用同一張 defaultImg.jpg,當圖片資源相同,瀏覽器後續請求會直接拿瀏覽器的 cache 快取用,這樣就沒問題了。

小結:圖片 LazyLoad 的關鍵價值

  • 減少資源浪費、提升初始載入速度
  • 改善 UX,尤其在慢速網路下效果顯著
  • Medium 式的漸進圖片載入為較好的典範
  • IntersectionObserver 是現今主流解法