Build a lazy loading image component for Nuxt.js

Google Lighthouse tests show lazy loading images is an easy win for performance. So here’s how.

Credit goes to Alex for his post on this topic

Import `lazysizes`

Lazysizes is a JS lazy loading library that has some powerful features.

lazysizes is a fast (jank-free), SEO-friendly and self-initializing lazyloader for images (including responsive images picture/srcset), iframes, scripts/widgets and much more. It also prioritizes resources by differentiating between crucial in view and near view elements to make perceived performance even faster.

First, follow the steps that Alex has detailed.

The first part of Alex’s article, installing and importing lazysizes into Nuxt, is what we need for this project.

The second part of the article, image optimisation, isn’t necessary for this component but is well worth a look.

Change the build extend method

The nuxt.config.js part is slightly different from Alex’s article.

Adding LazyImage: ['src'] to transformAssetUrls lets webpack know that the src should be transformed if needed.

extend(config, { isClient, isDev, loaders: { vue } }) {
vue.transformAssetUrls.LazyImage = ["src"];
}

As I run SSR using yarn generate, I need the asset url transform to happen on the server too; the isClient check is removed.

You can leave the other lines in from the article if you want, but they are not necessary for this component.

For more info on the transformAssetUrls property, checkout this bootstrap article.

Create a LazyImage component

Create a component /components/LazyImage.vue

<template>
<img class="lazyload" :data-src="src" src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkqAcAAIUAgUW0RjgAAAAASUVORK5CYII="
/>
</template>
<script>
export default {
props: {
src: { type: String, required: true }
}
};
</script>

The src attribute is initially set with a transparent pixel. This prevents showing the broken image icon on the page on load.

The data-src attribute (used by lazysizes) is set by relocating the src property from the parent.

Register the component for global use

Create a plugin /plugins/components.js

import Vue from "vue";import LazyImage from "@/components/LazyImage";Vue.component("LazyImage", LazyImage)

Register the plugin in the nuxt.config.js

Using the LazyImage component

As the component is globally registered, you can use it anywhere you want.
In fact, you can use it everywhere (probably).
For fun, search and replace <img with <LazyImage and see what happens.

<LazyImage class="my-class" src="/some/asset.png" alt="something" />
<!-- becomes -->
<img class="my-class lazyload" data-src="/some/asset.png" alt="something" />

Any attribute not matched by the props object is added to the img tag automatically.

<!-- Can use property and event binding too -->
<LazyImage
class="my-class"
custom-attribute="custom value"
:src="transform(myObj.imageSrc)"
:alt="myObj.alt"
@click="doSomething"
/>

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store