Boost Web Performance: Mastering Image Optimization with WebP and Lazy Loading
This guide explores systematic image optimization for web applications, covering formats like WebP, lossless vs lossy compression, lazy loading, placeholder strategies, format fallback, monitoring, and practical code implementations to reduce image size, memory usage, and improve loading speed and user experience.
Background
During recent performance observations, it was found that images occupy a large proportion of page weight, causing blank flashes and loading delays on several pages.
Typical image‑heavy pages suffer from high first‑screen load time; Lighthouse analysis shows large image size and weight.
Optimizing these images can bring clear benefits to users and the company, but a systematic process is missing.
Before Starting
First review basic concepts such as image formats and lossless vs lossy compression.
Image Formats Overview
jpg/jpeg
png
gif
WebP
Avif
Jpeg XL
Lossy vs Lossless Compression
Lossy Compression
Lossy compression reduces data size by discarding less important information, resulting in files that are smaller on disk and in memory but differ slightly from the original.
For web image loading, lossy compression is preferred to minimize memory usage and speed up decoding.
Lossless Compression
Lossless compression reduces file size without losing any information, allowing exact reconstruction after decompression. It is used in ZIP, gzip, etc., but does not reduce memory usage after decoding.
Therefore, to reduce memory consumption, lossy compression must be used.
WebP Overview
Concept
WebP is a modern image format offering both lossless and lossy compression. Compared with PNG, lossless WebP is 26% smaller; at equal SSIM quality, lossy WebP is 25‑34% smaller than comparable JPEG. Lossless WebP supports transparency with only 22% extra bytes, and lossy WebP can also support transparency, often three times smaller than PNG.
Examples show WebP’s advantages in real‑world sites such as YouTube and Douyin PC.
Optimization Ideas
Image optimization can be divided into loading stage and display stage.
Loading Stage
Image Size
Reducing image file size directly shortens network transfer time, improving first‑contentful‑paint and related metrics.
Memory Usage
Even if file size is reduced, memory usage may remain high; optimizing memory consumption speeds up decoding and rasterization, reducing page jank.
Display Stage
Placeholder Images
Placeholders give users a perceived loading progress, reducing abandonment.
Lazy Loading
Lazy loading defers unnecessary resource requests, saving bandwidth and memory.
Format Fallback
Because browser support for image formats varies, a fallback strategy (e.g., WebP → PNG) ensures compatibility while maximizing performance.
Error Placeholder
Provide a fallback visual when all loading attempts fail.
Practice – Experiment Stage
Image Compression
Use the existing platform to generate multiple formats (original, WebP, Avif) with a chosen compression ratio (e.g., 75%). The image list includes backup URLs for fallback.
type ImgUrlList = {
// original
origin: string,
// WebP format
webp: string,
// AVIF format
avif: string,
}The multi‑URL approach enables automatic fallback when a format is unsupported.
Browser statistics show Chrome 78.66% (min version 55) and Firefox min version 99, both supporting WebP; IE usage is negligible, so fallback to PNG is mainly for IE.
Image Loading
Implement the display‑stage flow using a custom image observer library that provides error retry and format fallback.
import type ImageObserver from 'xxxxxxxxx';
let imgObserver: ImageObserver;
export async function getImgObserver(): Promise<ImageObserver> {
if (imgObserver) return imgObserver;
const [ImageObserverSDK, LoggerSDK] = await Promise.all([
import('xxxxxxxxx'),
import('xxxxxxxxx-logger')
]);
const ImageObserver = ImageObserverSDK?.default;
const Logger = LoggerSDK?.default;
if (ImageObserver && Logger) {
imgObserver = new ImageObserver({
plugins: [Logger],
divider: { dataSrc: 'src', backUpSrc: 'backup-src' },
logger: { user_unique_id: 'cccccc', app_id: 111111 }
});
}
return imgObserver;
}Lazy loading is handled manually via IntersectionObserver:
const observerCb: IntersectionObserverCallback = useCallback((entries, observer) => {
const entry = entries[0];
if (entry.isIntersecting) {
setImgVisible(true);
observer.disconnect();
}
}, []);
const { updateObserverEl } = useIntersectionObserver({ cb: observerCb });Loading Data Reporting
Use a logger plugin to report attempts, retries, results, and timings, enabling analysis of format success rates and fallback behavior.
Optimization Feedback
Based on collected data, decide whether to experiment with newer formats (e.g., AVIF) or adjust CDN settings, and verify that fallback strategies work as expected.
Practice – Stable Stage
After validation, remove the heavy monitoring code and rely on native browser handling, while still supporting format fallback via the picture element.
const pictureRender = () => {
const { webp, avif, image } = remain.urlList;
return (
<picture>
<source srcSet={avif} type="image/avif" />
<source srcSet={webp} type="image/webp" />
<img src={image} onError={() => onError?.()} {...remain} />
</picture>
);
};The picture tag automatically selects the best supported format and falls back gracefully.
References
Links to articles on WebP, image compression, and responsive images are provided for further reading.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
