Improving Performance of Nuxt with Lazy Pattern
Tags: vue, javascript, webdev, tutorial
Published: 2023-03-13 08:24:49

One of my all time favorite pattern for improving performance in modern web applications is relatively simple to explain:

```
Just load what the user actually needs
```

This sounds really easy right? It should be, but believe me, with modern frameworks and with the pace of development we usually forget about this pattern and we put everything inside our application, and eventually for our users. 

This results in huge code bundles, megabytes of data transfer for the users, and bad performance. 

And the medicine is in the reach of our hands. When a user don't need it, just defer the loading of it until the time that it will be.

Let's take one of my favourite examples on the table. Imagine that your website (homepage) has a header, a banner and a footer that is right below the fold. 

Header contains a company logo, banner contains a product image and in the footer you have X images of company members (or any other section with images basically).

There is no need to fetch the images in the footer that are below the fold as user will not see them. So what is the point of fetching them actually? There isn't. And this is just the first example.

For more, check out next sections ;)

## Lazy Loading Images

Lazy loading images allows to improve the performance of your website which also results in better experience for your users. Take a look at the below GIF for a great visual representation with cats :)

<img width="100%" style="width:100%" src="https://wp-rocket.me/wp-content/uploads/2021/06/lazy-loading-chrome.gif">

This can be achieved by using the native `img` attribute called `loading`. To enable lazy loading just set its value to `lazy`. 

You can read more about it [here]( https://web.dev/lazy-loading-images/)

The result of implementing lazy loading can be observerd here:

![Lazy Loading Images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5vou9r3j17s9jul86jo.png)

*Source: https://addyosmani.com/assets/images/without-lazyload@2x.png*

In Nuxt ecosystem, it is best to use the NuxtImage module that comes with the support for lazy loading images as well and you can check it out [here](https://v1.image.nuxtjs.org/components/nuxt-img#loading)

To use the lazy loading just set the prop like following:

```html
<nuxt-img src="/nuxt-icon.png" loading="lazy" />
```

And with this change, the request for these assets will be delayed until they will be in the viewport.

Important note!

Remember to not use the `loading="lazy"` attribute on an element that is supposed to be a Largest Contentful Paint.


## Components Dynamic Imports

Nuxt allows to very easily utilize the components dynamic imports patter. To dynamically import a component (also known as lazy-loading a component) all you need to do is add the Lazy prefix to the component's name:

```vue
<template>
  <div>
    <TheHeader />
    <slot />
    <LazyTheFooter />
  </div>
</template>
```

This is particularly useful if the component is not always needed. By using the Lazy prefix you can delay loading the component code until the right moment, which can be helpful for optimizing your JavaScript bundle size.

You can read more about it [here](https://nuxt.com/docs/guide/directory-structure/components#dynamic-imports)

## Lazy Data Fetching Composables

Both `useLazyFetch` and `useLazyAsyncData` work as a wrapper around regular `useFetch` and `useAsyncData` that triggers navigation before the handler is resolved by setting the `lazy` option to `true`. By default, `useFetch` and `useAsyncData` blocks navigation until its async handler is resolved.

The `lazy` option for these composables works like following:

```
lazy: whether to resolve the async function after loading the route, instead of blocking client-side navigation (defaults to false)
```

Take a look at the below code sample to see how these Lazy alternatives work:

```vue
<template>
  <div>
    {{ pending ? 'Loading' : count }}
  </div>
</template>

<script setup>
/* Navigation will occur before fetching is complete.
  Handle pending and error states directly within your component's template
*/
const { pending, data: count } = useLazyAsyncData('count', () => $fetch('/api/count'))

watch(count, (newCount) => {
  // Because count starts out null, you won't have access
  // to its contents immediately, but you can watch it.
})
</script>
```

You can read more about it [here](https://nuxt.com/docs/api/composables/use-lazy-async-data) and [here](https://nuxt.com/docs/api/composables/use-lazy-fetch)

## Lazy Hydration

This concept allows you to have full control over the process of hydrating the HTML with JavaScript by utilizing concepts such as on-interaction, on-scroll, etc. I wrote about this concept already in my previous article that you can check out [here](https://dev.to/jacobandrewsky/improving-performance-of-nuxt-with-delayed-hydration-4cif)

## Summary

Nicely done! Now, you know more about the Lazy Pattern and how you can start using it in your applications to improve the performance and deliver better experience to your users. Let me know about other useful patterns for developing modern web applications :)