Lazy load embed videos by using facade image in Next JS

Lazy load embed videos by using facade image in Next JS

Optimize your next js website by using facade image for the embedded videos

ยท

3 min read

Introduction

Videos are a great way of communicating with users whether it is a tutorial about a particular topic, an introduction of your company/yourself, a testimonial about a product, etc.

One of the easiest ways of putting the videos on your website is by using embedded videos which are provided by Youtube, Vimeo, etc.

The Need

The problem comes when you're trying to optimize your website and the website's core web vitals are affected by the embedded videos maybe it reduces score FID (First in display) if the embed video is inside the hero section or you're getting a reduce unused javascript opportunity in performance report by the lighthouse or pagespeed

One of the ways to optimize the embedded video is to only load an image with a play icon on the initial load rather than loading the whole video and then whenever the user clicks the play icon we will replace the facade image and the play icon with the actual embed video.

Untitled-2022-08-13-1605.png

Implementation

Styles

.video{
    height:300px;
    width:550px;
    position:relative;
    background-color:darkgray;
    display:flex;
    justify-content:center;
    align-items:center;
}

.video iframe{
    height: 100%;
    width:100%;
}

.play{
    height:50px;
    width:50px;
    z-index: 1;
}

.container{
    display: flex;
    justify-content: center;
    align-items:center;
    height: 100vh;
}

Important: You will be required to add the hostname in the domains for accessing the image from 'img.youtube.com' as you will be using the next image. The configuration is done inside of the next.config.js

module.exports = {
  images: {
    domains: ['img.youtube.com'],
  },
}

JavaScript Code

import Image from "next/image";
import React, { useState,useEffect } from "react";
import style from './styles.module.css';

const embedID = "0RKpf3rK57I";

const Embed = () => {
  const [imageClicked, setImageClicked] = useState(false);

  return (
    <div className={style.container}>
    <div className={style.video}>
      {!imageClicked ? (
        <>
          <Image
            src={`https://img.youtube.com/vi/${embedID}/sddefault.jpg`}
            layout="fill"
            objectFit="cover"
            alt="yt thumbnail"
            priority
          />
          <img id="play-button" className={style.play} src="http://addplaybuttontoimage.way4info.net/Images/Icons/7.png" alt="play button" />
        </>
      ) : (
        <iframe
          frameBorder="1"
          allowFullScreen
          src={
            imageClicked
              ? `https://www.youtube.com/embed/${embedID}?rel=0&showinfo=0&autoplay=1`
              : ""
          }
          title="youtube video"
        />
      )}
    </div>
    </div>
  );
};
export default Embed;

We will be using a state 'imageClicked' to check if the play icon has been clicked or not. So as you can see in the above code we are conditionally rendering the Image or the embed video using the ternary operator.

Now we need to add the useEffect that will add an 'click' event listener on the play icon during the mount of the component. But make sure to add the third parameter of 'once' equal to true so that it listens for the event only once.

The event handler sets the state of the imageClicked state to true and then the embed video is loaded due to conditional rendering

  const onThumbnailClick = () => {
    setImageClicked(true);
  };

  useEffect(()=>{
    const playImg = document.querySelector("#play-button");

    playImg.addEventListener("click",onThumbnailClick,{once:true});
  },[])

Conclusion

Having an embedded video can be very helpful for the user but as frontend developers, we need to make sure that the page is optimized and the core web vitals score is on the green side. In this article, we discussed one of the ways to optimize the embedded video for youtube embedded video, the steps will be the same for other services like Vimeo as well.

Credits: The youtube embed video for this article was taken from the latest fireship video.

You can also check out the code here.

๐Ÿ™Œ Thank you for reading, I hope this article was helpful for you. You can connect with me on Twitter and LinkedIn.

ย