Skip to main content

[Lv1] Image Loading Optimization: Four-layer Lazy Load

A four-layer image lazy-loading strategy that significantly reduces first-screen traffic and improves perceived loading speed.


Situation​

A gallery page may include hundreds of images, but users usually view only the first few items.

Typical issues without optimization:

  • Huge initial payload from image requests
  • Long first-screen loading time
  • Scroll jank on lower-end devices
  • Wasted bandwidth for images users never see

Task​

  1. Load only images near the viewport
  2. Preload just before entering view
  3. Control concurrent image requests
  4. Avoid redundant downloads during rapid navigation
  5. Keep first-screen image traffic under a strict budget

Action: Four-layer strategy​

Layer 1: Visibility detection with IntersectionObserver​

const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
loadImage(entry.target as HTMLImageElement);
observer.unobserve(entry.target);
}
});
},
{ rootMargin: '120px 0px', threshold: 0.01 }
);

This triggers loading only when an image is close to view.

Layer 2: Placeholder and progressive experience​

  • Use blurred thumbnail / skeleton placeholder
  • Reserve width/height to prevent layout shift
  • Replace placeholder after image decode
<img src="/placeholder.webp" data-src="/real-image.webp" width="320" height="180" alt="cover" />

Layer 3: Concurrency queue​

const MAX_CONCURRENT = 6;
const queue: Array<() => Promise<void>> = [];
let active = 0;

async function runQueue() {
if (active >= MAX_CONCURRENT || queue.length === 0) return;
const task = queue.shift();
if (!task) return;

active += 1;
try {
await task();
} finally {
active -= 1;
runQueue();
}
}

Limits network pressure and avoids request spikes.

Layer 4: Cancellation and deduplication​

  • Cancel outdated requests via AbortController
  • Use URL-level in-memory map to deduplicate loading
  • Skip re-requesting already successful assets
const inflight = new Map<string, Promise<void>>();

Result​

Example impact after rollout:

  • First-screen image payload reduced drastically
  • Faster first meaningful paint
  • Better scroll smoothness
  • Lower bounce rate on mobile networks

Interview-ready summary​

I combine viewport detection, placeholder rendering, request queue control, and cancellation/deduplication. This avoids loading images users never see and keeps both network and UI responsive.