Lazy Load Vue Component When It Becomes Visible
In today's fast-paced digital world, website performance is crucial for engaging users and achieving online success. Landing pages, serving as the virtual storefronts of businesses, hold immense importance in capturing audience attention and driving conversions. However, when it comes to large sites like landing pages, performance optimization becomes a challenge without compromising functionality.
That's where lazy loading Vue components come in. By deferring the loading of non-essential elements until they are visible, developers can enhance the user experience while ensuring swift load times on vital landing pages.
Lazy loading is a technique that prioritizes the initial rendering of critical content while postponing the loading of secondary elements. This approach not only reduces the initial page load time but also conserves network resources, resulting in a snappier and more responsive user interface.
In this blog post, I'll show you a simple mechanism to lazy load your Vue components if they become visible using the Intersection Observer API.
Intersection Observer API
The Intersection Observer API is a powerful tool that allows developers to efficiently track and respond to changes in the visibility of elements within the browser's viewport.
It provides a way to asynchronously observe intersections between an element and its parent, or between an element and the viewport. It offers a performant and optimized solution for detecting when elements become visible or hidden, reducing the need for inefficient scroll event listeners and enabling developers to enhance user experiences by selectively loading or manipulating content precisely when it becomes necessary.
It is typically used to implement features such as infinite scrolling and image lazy loading.
Async Components
Vue 3 provides a defineAsyncComponent to asynchronously load components only when they are needed.
It returns a Promise that resolves to a component definition:
It is also possible to handle error and loading states:
We will use this functionality to load our components asynchronously when they become visible.
Lazy Loading Components When They Become Visible
Let's now combine the Intersection Observer API and the defineAsyncComponent
function to load our components asynchronously when they become visible:
Let's break down the code above:
We create a lazyLoadComponentIfVisible
function that accepts the following parameters:
componentLoader
: A function that returns a Promise that resolves to a component definitionloadingComponent
: A component to use while the async component is loading.errorComponent
: A component to use if the load fails.delay
: Delay before showing the loading component. Default: 200ms.timeout
: The error component will be displayed if a timeout is provided and exceeded. Default: Infinity.
The function returns defineAsyncComponent
which includes the logic to load the component asynchronously when it becomes visible.
The main logic happens in loadingComponent
inside of defineAsyncComponent
:
We create a new component using defineComponent
which includes a render function that renders the loadingComponent
inside a wrapper div
that was passed to lazyLoadComponentIfVisible
. The render function includes a template ref to the root element of the loading component.
Inside onMounted
we check if the IntersectionObserver
is supported. If it is not supported, we immediately load the component. Otherwise, we create an IntersectionObserver
that observes the root element of the mounted loading component to detect when it becomes visible. When the component becomes visible, we cleanup the observer and load the component.
You can now use this function to lazy load your components when they become visible:
StackBlitz Demo
Try it yourself in the following StackBlitz demo:
If you scroll the page down until the component becomes visible, you will see in the Network tab in your browser DevTools that the component is loaded asynchronously:
Conclusion
In this article, you learned how to lazy load Vue components when they become visible using the Intersection Observer API and the defineAsyncComponent
function. This can be useful if you have a landing page with many components and want to improve the initial load time of your application.
Special thanks to Markus Oberlehner who wrote a similar article for Vue 2 which inspired me to write this article for Vue 3.
If you liked this article, follow me on Twitter to get notified about new blog posts and more content from me.
Alternatively (or additionally), you can subscribe to my weekly Vue newsletter:
A Comprehensive Guide to Data Fetching in Nuxt 3
With Nuxt 3's rendering modes, you can execute API calls and render pages both on the client and server, which has some challenges. For example, we want to avoid duplicate network calls, efficient caching, and ensure that the calls work across environments. To address these challenges, Nuxt provides a built-in data fetching library ($fetch) and two composable (useFetch and useAsyncData).
Focus & Code Diff in Nuxt Content Code Blocks
Custom code blocks are essential for my blog as my articles usually contain a lot of code snippets. My blog is powered by Nuxt Content v2, which is a Nuxt 3 module. I already wrote an article about how you can create custom code blocks using Nuxt Content v2.