DEV Community

Cover image for Optimizing Web Performance: Lazy Loading Images and Components
Henrique Schroeder
Henrique Schroeder

Posted on • Edited on

Optimizing Web Performance: Lazy Loading Images and Components

Optimizing web performance is crucial for providing a superior user experience, improving SEO, and increasing conversion rates. For intermediate and experienced developers, lazy loading images and components is an advanced technique that can make a significant difference in web application performance. Let's explore the more technical aspects of this practice and how to implement it efficiently using native JavaScript, lazysizes, React.lazy, Dynamic Imports, and next/script.

Advanced Benefits of Lazy Loading

  1. Improvement of Largest Contentful Paint (LCP):

    • LCP is one of Google's key Core Web Vitals indicators. By deferring the loading of non-critical images and components, the rendering time of the largest visible element in the initial viewport is significantly reduced.
  2. Reduction of Resource Consumption:

    • Lazy loading reduces the load on the server and network by avoiding unnecessary requests, improving overall system efficiency and allowing resources to be allocated more effectively.
  3. Enhancement of Responsiveness:

    • Applications that use lazy loading are more responsive, especially on mobile devices, providing a smoother experience for end users.

Implementation of Lazy Loading for Images with Native JavaScript

Complete Example:

  1. HTML:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Lazy Loading Example</title>
    <style>
        .lazy {
            opacity: 0;
            transition: opacity 0.3s;
        }
        .lazy-loaded {
            opacity: 1;
        }
    </style>
</head>
<body>
    <h1>Lazy Loading Example</h1>
    <img data-src="image1.jpg" alt="Image 1 Description" class="lazy">
    <img data-src="image2.jpg" alt="Image 2 Description" class="lazy">
    <img data-src="image3.jpg" alt="Image 3 Description" class="lazy">
    <script src="lazyload.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  1. JavaScript (lazyload.js):
document.addEventListener("DOMContentLoaded", function() {
    const lazyImages = document.querySelectorAll('img.lazy');
    const lazyLoad = (image) => {
        image.src = image.dataset.src;
        image.onload = () => {
            image.classList.remove('lazy');
            image.classList.add('lazy-loaded');
        };
    };

    if ("IntersectionObserver" in window) {
        const observer = new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    lazyLoad(entry.target);
                    observer.unobserve(entry.target);
                }
            });
        });

        lazyImages.forEach(img => {
            observer.observe(img);
        });
    } else {
        // Fallback for browsers that do not support IntersectionObserver
        const lazyLoadThrottle = () => {
            lazyImages.forEach(img => {
                if (img.getBoundingClientRect().top < window.innerHeight && img.getBoundingClientRect().bottom > 0 && getComputedStyle(img).display !== "none") {
                    lazyLoad(img);
                }
            });
        };

        window.addEventListener("scroll", lazyLoadThrottle);
        window.addEventListener("resize", lazyLoadThrottle);
        window.addEventListener("orientationchange", lazyLoadThrottle);
    }
});
Enter fullscreen mode Exit fullscreen mode

Implementation of Lazy Loading for Images with lazysizes

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Lazy Loading with lazysizes</title>
    <style>
        .lazyload {
            opacity: 0;
            transition: opacity 0.3s;
        }
        .lazyloaded {
            opacity: 1;
        }
    </style>
</head>
<body>
    <h1>Lazy Loading with lazysizes</h1>
    <img data-src="image1.jpg" alt="Image 1 Description" class="lazyload">
    <img data-src="image2.jpg" alt="Image 2 Description" class="lazyload">
    <img data-src="image3.jpg" alt="Image 3 Description" class="lazyload">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.3.2/lazysizes.min.js" async></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Implementation of Lazy Loading for Components with React.lazy and Suspense

React:

import React, { Suspense, lazy } from 'react';

const LazyComponent = lazy(() => import('./LazyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Implementation of Lazy Loading for Components with Dynamic Imports in Next.js

Next.js:

import dynamic from 'next/dynamic';

const DynamicComponent = dynamic(() => import('../components/DynamicComponent'), {
  loading: () => <p>Loading...</p>,
  ssr: false
});

export default function Home() {
  return <DynamicComponent />;
}
Enter fullscreen mode Exit fullscreen mode

Additional Optimizations with next/script

Next.js:

import Script from 'next/script';

function MyApp() {
  return (
    <>
      <Script src="https://example.com/somescript.js" strategy="lazyOnload" />
      <Component />
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Final Considerations

Implementing lazy loading with native JavaScript, lazysizes, React.lazy, Dynamic Imports, and next/script is a powerful approach to improving the performance of your web applications. These techniques allow precise control over when and how resources are loaded, providing a faster and more efficient user experience.

When applying these advanced techniques, it's important to monitor performance impacts using tools like Lighthouse, Google Analytics, and Core Web Vitals reports. Continuous analysis and iterative optimization will ensure that your applications deliver the best possible experience.

References

  1. Google Developers: Native Lazy Loading
  2. MDN Web Docs: Intersection Observer API
  3. Web.dev: Lazy Loading
  4. Google Developers: Optimize LCP
  5. Lazysizes GitHub Repository
  6. React Documentation: Code Splitting
  7. Next.js Documentation: Dynamic Import

Translated post with the help of AI

Top comments (0)