Build a lazy loading image component for Nuxt.js
In the most lazy way possible.
--
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"
/>