Special Black Friday Offer

Get NitroPack with up to 37% OFF

Days
:

Hours
:

Minutes

JavaScript Lazy Loading: What It Is and How to Use It

Last updated on Aug 27th, 2024 | 9 min

A single slow-loading page can make or break a customer relationship.

Studies have shown that even a 0.1-second load time shift can influence every aspect of the user journey. The list of tasks to make your website faster seems never-ending.

But you already knew that.

Whether dealing with image-heavy websites, complex single-page applications, or content-rich platforms, JavaScript lazy loading offers a flexible solution to optimize your site's performance.

So, in the following lines, you will discover everything you need to know about JavaScript lazy loading. We’ll cover what it is, how it works, and how to implement it to boost your website’s performance.

Although implementing JavaScript lazy loading can be challenging, with NitroPack, you can sit back and relax as it automatically handles this task.

Leverage 60+ world-class performance optimization techniques with NitroPack. Get started now →

What Is JavaScript Lazy loading and How Does It Work? 

So, what exactly is lazy loading?

Essentially, it is a clever technique that prioritizes loading essential content first, leading to a more responsive website. JavaScript lazy loading defers the loading and execution of JavaScript files and elements until needed. 

It loads resources only when necessary, usually when the user scrolls to a specific part of the webpage or interacts with a particular element. 
 

User navigation triggers the lazy loading of JavaScript

Specific actions can trigger lazy loading when a user navigates through a webpage. For instance, scrolling down a page can prompt the loading of images, videos, or JavaScript-driven elements that are not immediately visible when the page first loads.
 

Understanding the fold

The "fold" refers to the portion of a webpage that is visible without scrolling. Content above the fold loads immediately, while content below the fold can be lazy-loaded. 

This approach ensures that users see the essential parts of the page quickly, improving the site's perceived performance. By loading this essential content upfront, you'll score a quick First Contentful Paint (FCP), leading to a better user experience. In the background, JS lazy loading will help you ensure your Largest Contentful Paint (LCP) is also optimized, contributing to a passing grade on Core Web Vitals. 

Expert tip: While First Contentful Paint (FCP) is important for measuring perceived load speed, Largest Contentful Paint (LCP) plays a more significant role in passing Core Web Vitals. For more information, read our guide about fixing LCP.

 

PageSpeed Insights Core Web Vitals


What counts as JavaScript?

Let's break this down a bit more. Lazy loading doesn’t involve just images or basic content; it's also about:

  • Interactive components, such as expandable sections or tab interfaces that require JavaScript to function
  • Third-party widgets like social media feeds or chatbot interfaces
  • Animations can be resource-intensive and slow down the page if loaded prematurely.
  • JavaScript from third-party tracking tools

 

Advantages and Disadvantages of JS Lazy Loading 

JavaScript lazy loading is a powerful tool that can boost your website's performance.

But it's not a one-size-fits-all solution. Let's explore the good, the bad, and the "hmm, that's something to think about" aspects of JavaScript lazy loading.
 

Pros of lazy loading JavaScript

Discover the benefits that make JavaScript lazy loading a great choice. 

  • Improved page loading speed: Users get to see the important parts of your page almost immediately, without unnecessary delays. 
  • Fixing tricky PSI diagnostic warnings: This helps reduce JS execution time, eliminate render-blocking resources, avoid chaining critical requests, and minimize main thread work, as highlighted in Page Speed Insights reports.

PageSpeed Insights JavaScript related warnings

  • Reduced initial load: Delaying the loading of JavaScript files reduces the initial load size, helping pages load faster. This can even increase the average conversion rate, as users will likely stay on the page and engage with its content.
  • Improves user experience: An uninterrupted website experience keeps users engaged and makes the site more responsive. Smooth transitions and immediate content delivery encourage users to stay longer and interact more with your site.
  • Saves bandwidth: Lazy loading reduces the initial data transfer, conserving user and server bandwidth.
  • Better SEO performance: Since Google switched to mobile-first indexing, a website's mobile speed is even more crucial. Lazy loading helps you ace those Core Web Vitals, increasing your chances of ranking higher in search results.  
     

Cons of lazy loading JavaScript

  • Technical knowledge: Implementing lazy loading requires technical knowledge and understanding of JavaScript and web performance optimization. In other words, you need help from a developer. NitroPack's Lazy Loading Feature for Images can help you automate this process.
  • Testing and implementation: Properly implementing lazy loading requires thorough testing to ensure that all scripts are loaded correctly and that there are no negative impacts on functionality or user experience. This can be time-consuming and requires careful debugging.
  • Possibility to lazy load the wrong elements: If not implemented correctly, lazy loading can result in the wrong elements being lazy loaded, negatively impacting the user experience. For example, if a script required for a critical feature is lazily loaded, it could cause the feature to fail or load improperly.
  • Additional overhead: Lazy loading introduces additional overhead regarding JavaScript code and processing, which can impact performance if not optimized properly. This overhead can be minimized by using efficient lazy-loading libraries or frameworks.
  • Incompatibility with certain features: Some JavaScript features, such as Intersection Observer, may not be supported in older browsers. As a result, lazy loading may not function properly in these browsers, and you may need to explore other compatibility options.

 

How to Apply Lazy Loading to JavaScript Resources 

Implementing lazy loading for JavaScript resources can initially seem like getting lost in a maze, but don't worry—we're here to simplify things.

Below are a few ways to implement Javascript lazy loading. Try them and see what works best for you.
 

Code splitting

Code splitting involves breaking your JavaScript into smaller, more manageable chunks. This ensures that only the code required for the current page is loaded initially, with additional code being loaded as needed. This approach can greatly reduce the initial load time of your web pages.

Code splitting example

Steps for code splitting:

  • Use tools like Webpack to split your code into chunks.
  • Break down your code based on routes, components, or features.
  • Load these chunks dynamically and on demand.
     

Asynchronous loading

Asynchronous loading allows JavaScript files to load without blocking the rendering of the rest of the page.

  • Async attribute: This attribute makes the script load in the background while the rest of the page continues to render. Once the script is downloaded, it is executed immediately.
  • Defer attribute: Similar to async, defer also loads scripts in the background. However, it ensures that all scripts with the defer attribute are executed in the order they appear in your HTML document only after the entire HTML structure has been parsed.

Async defer example

Steps for asynchronous loading: 

  • Determine the JS files critical for initial rendering.
  • Add the async attribute for non-essential scripts that can load in the background.
  • Add the defer attribute for scripts that should execute in the order they appear in the HTML, after the document has been parsed.
     

Dynamic imports

Dynamic imports enable you to load JavaScript modules only when they are needed. This is particularly useful for loading features or components not immediately required when the page loads.

Dynamic import example

Steps for dynamic imports: 

  • Determine features or modules that aren't needed immediately.
  • Use the import() function to load these modules as needed.
  • Trigger loading of modules based on user actions or specific events.
     

Intersection observer API for loading scripts

The Intersection Observer API is a powerful tool for lazy loading. It lets you detect when elements (like images or JavaScript resources) enter the viewport. When an element comes into view, the corresponding script can be loaded, ensuring resources are only loaded when necessary.

The observer API is a pretty complex beast, so we strongly recommend referring to the Mozdev documentation for examples and explanations of how to implement it. With this in mind, here is an example of implementation for the Observer API

Intersection observer api

Expert tip: This code example uses the IntersectionObserver API to lazily load JavaScript when the target elements enter the viewport. The lazy-load-script class and data-src attribute should be added to the HTML elements that trigger the lazy loading.

 

When the element with the class lazy-load-script enters the viewport, the script specified in the data-src attribute is dynamically created and appended to the body, thus being loaded. This method can be applied to any existing HTML element, not just empty divs, providing flexibility in how lazy-loaded scripts are integrated into your page.

Steps for implementing the intersection observer: 

  • Create an intersection observer to detect the visibility of elements within the viewport.
  • Observe target elements: Use the observer.observe() method to start observing elements that will be lazy loaded.
  • Load scripts: When an element enters the viewport (entry.isIntersecting), create and append a script element with the src from data-src.
  • Remove element from the observer: Once the script is loaded, use observer.unobserve() to stop observing the element.
     

Lazy loading on the scroll event

This strategy involves loading resources as the user scrolls down the page. For example, if a user scrolls to a specific section, you can trigger the loading of the JavaScript code associated with that section. This is useful for loading content that's not immediately visible but will be needed as the user explores the page.

Expert Tip: The following code example for lazy loading an image on a scroll event uses the Intersection Observer API, which efficiently detects when an element enters the viewport and then loads the required resources.

 

Lazy loading example

Steps for lazy loading elements on scroll events: 

  • Identify elements that are not visible initially to lazy load.
  • Use the IntersectionObserver API to detect when these elements enter the viewport.
  • When an element is about to enter the viewport, load the necessary resources (e.g., set the src attribute for images).
     

Lazy loading JavaScript for images

Instead of loading all images when a page initially loads, lazy loading defers the loading of off-screen images until the user scrolls near them. While many open-source scripts and code libraries, like Lozad.js and Vanilla Lazyloadd, handle this, understanding the underlying logic of lazy loading JS for images is beneficial. 

Here are some key points on how to effectively lazy load images:

  • Identify images that need lazy loading. These typically include images below the fold, which are not initially visible to the user. For images that should be lazy-loaded, use a class (e.g., lazy-load-image) and data-src attribute.
  • Implement intersection observer: Use the Intersection Observer API to monitor the visibility of these images. 
  • Load Images on Visibility: Replace the data-src attribute with the src attribute when images enter the viewport.
  • Provide a Fallback Image (Optional): You can optionally include a fallback image to display while the actual image loads.
  • Test your implementation: After implementing lazy loading for images, thoroughly test your website to ensure the technique works as expected.

Example of lazy loading JS for images:

Lazy loading js image

Expert Tip: The Intersection Observer API efficiently monitors when images enter the viewport, triggering their loading only when necessary. This approach improves performance compared to traditional scroll event listeners.

 

How to Lazy Load JS Resources With NitroPack 

Instead of constantly updating your code manually or hiring a web developer to do it, you can install NitroPack and lazy load your resources in a couple of minutes. 

NitroPack's Delayed Scripts feature allows you to lazy load your JS scripts:

NitroPack delayed scripts

 All you have to do is find the script you want to delay, copy the first line and paste it into NitroPack:

Script example

Then, NitroPack will execute the script with a delay of about 6500ms, thus giving loading priority to your other scripts, which are much more important for the user experience.

Simply put, it's an efficient and easy way to get the most out of JS lazy loading without the manual hassle. 

Get JS lazy loading and 60+ other performance features. Install NitroPack today 

Best practices (be)for(e) JavaScript lazy loading 

Before you jump into JavaScript lazy loading, let's ensure it's your best solution. You could start with simpler approaches like optimizing image sizes, minifying code, and leveraging caching. If lazy loading is still your choice, here are some best practices for a smooth setup.

Optimize media files

Before diving into lazy loading, ensure your images and videos are optimized for quick loading. Consider the following steps:

  • Compress without compromising quality: Use tools like TinyPNG or JPEGmini to reduce file sizes while maintaining visual quality.
  • Choose the right format: Use formats like WebP for images and MP4 for videos to achieve better compression and faster loading.
  • Resize according to common viewport sizes: Scale images and videos to fit the most common screen resolutions. For example, if your site’s main content area is 1200 pixels wide, there’s no need to load an image that’s 4000 pixels wide.

Use placeholder elements

Using little placeholder pictures or low-quality versions of your images is also a good idea. This keeps your page from jumping around as the real images load, which is crucial for user experience and SEO. These placeholders let users know the content is loading so they know what to expect.

Implement intersection observer

Consider using the Intersection Observer API. It's a great way to detect when an element comes into view, making it perfect for lazy loading. It's more efficient than older techniques involving event listeners for scroll events, as it’s specifically designed for this purpose.

Test across multiple devices and connections 

Remember to test your lazy loading implementation across different devices and connections. Make sure your site looks good on phones, tablets, and older browsers. Check how it loads on slow connections, too, including 3G. You want to ensure everyone has a good experience.

Consider SEO implications

Ensure search engines can crawl and index your lazy-loaded content. Follow Google's guidelines for lazy loading and use SEO tools to check if everything is working as expected. You might need server-side or dynamic rendering for complex setups to help crawlers access your content.

Fallback for unsupported browsers

Have a fallback plan for older browsers. Modern browsers support Intersection Observer and loading="lazy," but older ones might not. Load all content immediately for these browsers. Having a fallback ensures no users are left out, no matter their browser. 

Monitor performance

Use performance monitoring tools to measure the impact of lazy loading on your site. Tools like Google's Lighthouse, PageSpeed Insights, and WebPageTest can provide insights into how well your lazy loading implementation works.

 

Frequently asked questions

Have we covered everything? We sure hope so. Before we wrap this up, here are some frequently asked questions that should address any lingering doubts. 

1. How can I lazy load interactive components like expandable sections or tab interfaces? 

Interactive components that require JavaScript can be lazy-loaded using the same logic as the images exemplified above using the Intersection Observer API. Simply set these components to load when they come into view to ensure that your page loads faster initially and only moves to load the necessary JavaScript when the user interacts with your expandable section or tabbed element. 
 

2. What about third-party widgets, tracking codes, social media feeds, or chatbot interfaces? 

Third-party widgets can and should be lazy-loaded as they consume many resources and come with heavy scripts that can destroy your initial page load. You can use a lazy-loading library or the intersection Observer API to load third-party widgets only when they come into the user’s viewport. 

Third-party tracking scripts can also be deferred using lazy loading techniques. However, lazy loading requires more testing to ensure critical tracking information is not lost. We strongly recommend installing only the necessary tracking tools to avoid overloading your code.
 

3. What is the best way to handle animations that are resource-intensive?

Surprise, surprise: animations can also be lazy-loaded using the same logic of only being loaded when they are about to enter a viewport. This ensures that there is no delay in your initial load time. The best way to handle resource-intensive animations is by using the Intersection Observer API. 
 

4. What is the best way to implement lazy loading across different browsers?

The most important thing is to check whether the browser supports lazy loading. Earlier, we advised providing a fallback that loads content immediately. This is useful for older browsers that do not support IntersectionObserver or the loading=lazy attribute. 
 

5. This is too complicated. Are there any tools that can help implement lazy loading?

Of course! NitroPack’s lazy loading feature does all of these optimizations automatically for you. Alternatively, you can use several tools or libraries like the ones mentioned above (Lozad.js, Vanilla Lazyload, etc.) to simplify the implementation process.

Niko Kaleev
User Experience Content Expert

Niko has 5+ years of experience turning those “it’s too technical for me” topics into “I can’t believe I get it” content pieces. He specializes in dissecting nuanced topics like Core Web Vitals, web performance metrics, and site speed optimization techniques. When he’s taking a breather from researching his next content piece, you’ll find him deep into the latest performance news.