Create a Simple Reusable Image Lazy Loading Component in Laravel using Vue.js


Initial loading of big images can negatively affect your website's overall performance and can even lead to low SEO rankings. Google has indicated site speed (and as a result, page speed) is one of its algorithms used to rank page. A simple solution to this is to Lazy Load all big images. Many famous sites like Medium are already implemented this perfectly. Lazy Loading is a technique that defers loading of non-critical resources at page load time. Instead, these non-critical resources are loaded at the moment of need. Where images are concerned, "non-critical" is often synonymous with "off-screen". In the case of Medium, they load a very low-quality small image first in blur effect and then load a high-quality original image progressively.

In this tutorial, I will show you how to make a dead simple custom reusable lazy image loading component using Vue.js and implement it in your Laravel projects. This component is very simple to maintain and can even use outside of your Laravel project.  I will try to accomplish very similar effect as of Medium's Progressive image loader. In this component, we need to pass two props, Initial Image and Final Image. The initial image must be a low-quality version of the original image or a low-quality loader gif if you wish. You also have the option to set the blur level of the initial image. The final image is must be the high-quality original image which will load after the Initial window loading completed. This component will help as to greatly reduce the initial site loading time.

Let's Start Coding

First thing is to include Vue.js in our application. In the case of Laravel, you can easily include Vue.js using Laravel Mix.

Laravel Mix provides a fluent API for defining Webpack build steps for your Laravel application using several common CSS and JavaScript pre-processors. All you need to do is install Nodejs and NPM in your development system and run

npm install

to install all javascript dependencies in your application. The jQuery, Bootstrap, Vuejs, Axios and Lodash are already included in this setup.  Now just run

npm run watch 

to compile your assets. Don't forget to include app.css and app.js files in the public folders to your Laravel View Layouts.

Now Let's create our Vue component for Lazy Loading Images. 

The complete code for LazyLoadingImage.vue file is given below

<template>
    <img  
        itemprop="image" 
        v-bind:style="styleObject"
        v-bind:src="imageScr"
        v-bind:alt="alt"
    >
</template>

<script>
    export default {
        props: {
            initialImage: {
              type: String,
              required: true
            },
            finalImage: {
              type: String,
              required: true
            },
            alt: {
              type: String,
              default: ""
            },
            blurAmount: {
              type: Number,
              default: 5
            },
        },
        data() {
            return {
                imageScr : this.initialImage,
                loaded : false,
                completed : false,
                styleObject: {
                    filter: `blur(${this.blurAmount}px)`,
                    transition: "all 1s"
                }
            }
        },
        methods: {
            setWindowLoaded() {
                setTimeout(() => {
                    this.loaded = true;
                },100)
            },
            lazyLoad() { 
                if (this.loaded && !this.completed) {
                    this.completed = true;
                    this.imageScr = this.finalImage;
                    this.styleObject = {
                        transition: "all 1s"
                    };
                }
            },
        },
        mounted() {
            window.addEventListener('load', this.setWindowLoaded);

            window.addEventListener('scroll', this.lazyLoad);

        }
    }
</script>

 

The initialImage and finalImage are the required props. They should be strings. At the time of page loading, we set image source as initial image and then later when window load completed and the Final big image is completely loaded the image source switches. We use the load event listener to check whether the page is completely loaded. When it is done we use scroll event listener to listen to user scrolls and replace the images. This gives us a consistent time to load big Final Image in the background. Once the final image is replaced the completed will become true and thus further scroll events will not cause any load.

The alt prop is used to set the alt text for the image. This is not a required prop. Similarly, the blurAmount prop is used to set the blur amount at the time of initial load. We pass that prop to a styleObject which is bind to style property of image tag. A small transition is given to ensure cool animation effect. I added itemprop="image"  purely for the purpose of SEO. It is a structured data and you can remove it if you want.

Now Let's register LazyLoadingImage component globally by adding it to app.js file inside the resource/assets. Inside your app.js file add this line.

Vue.component('lazy-image', require('./components/LazyLoadImage.vue'));

 

Now let's use the image component inside our Laravel View as given below.

<lazy-image 
      initial-image="{{ asset('/images/loading.gif') }}" 
      final-image="{{ $post->image }}"
      alt="{{ $post->title }}"
      blur-amount="2"
      class="img-responsive1"
></lazy-image>

 

Now you may wonder about the class prop right?.  In Vue.js When you use the class attribute on a custom component, those classes will be added to the component’s root element ( and In our case Img tag). Existing classes on this element will not be overwritten.

The sample output image of above program is given below.

Sample output of Vue Lazy Loading Image Component

 

The Demo

You can demo the above application by Homepage or Blogs page of this site. I just share the exact codes I used on my blog to improve its initial loading time.

If anybody has any suggestions or doubts or need any help comment below and I try will respond to every one of you as early as possible.





Web development
16th Apr 2018 12:17:32 AM
PHP Laravel Javascript Vue.js
147