How to improve performance when rendering YouTube videos in NextJS with Sanity

3 replies
Last updated: May 21, 2023
Hi, while using NextJS with sanity I am facing performance issue as I add YouTube video in sanity text editor and then render it on website using ReactPortable Text Package.

Is there any better way to render the YouTube video so it don't affects the overall blogpage performence?
In RichComponents.tsx file I rendering video like this:


import YouTubeEmbed from "./YouTubeEmbed";
import getYouTubeID from "get-youtube-id";

export const RichTextComponents = {
  types: {
    image: ({ value }: any) => {
      return (
        <div className="relative w-full h-96 m-10 mx-auto">
          <Image
            className="object-contain"
            src={urlFor(value).url()}
            alt="Blog Post Image"
            fill
          />
        </div>
      );
    },
    youtube: ({ value }: any) => {
      const id = getYouTubeID(value.url);
      return id ? <YouTubeEmbed id={id} /> : null;
    },
  },

<YouTubeEmbed id={id} />
is a custom component that I have created

// YouTubeEmbed.tsx
import React from "react";

type YouTubeEmbedProps = {
  id: string;
};

const YouTubeEmbed: React.FC<YouTubeEmbedProps> = ({ id }) => (
  <div className="youtube-player mt-8 mb-8 justify-center flex">
    <iframe
      width="560"
      height="315"
      src={`<https://www.youtube.com/embed/${id}>`}
      title="YouTube video player"
      frameBorder="0"
      allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
      allowFullScreen
    ></iframe>
  </div>
);

export default YouTubeEmbed;
AI Update

Great question! The performance issue you're experiencing is common when embedding YouTube videos via iframes - they load immediately and can significantly slow down your page. Here are several strategies to optimize your YouTube embeds:

The best solution is to use a facade/lite embed approach. Install react-lite-youtube-embed:

npm install react-lite-youtube-embed

Then update your YouTubeEmbed.tsx:

import LiteYouTubeEmbed from 'react-lite-youtube-embed';
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'

type YouTubeEmbedProps = {
  id: string;
};

const YouTubeEmbed: React.FC<YouTubeEmbedProps> = ({ id }) => (
  <div className="youtube-player mt-8 mb-8 justify-center flex">
    <LiteYouTubeEmbed 
      id={id}
      title="YouTube video player"
    />
  </div>
);

export default YouTubeEmbed;

This loads a lightweight thumbnail initially and only loads the full iframe when users click to play, reducing initial page load by ~500KB per video.

2. Native Lazy Loading

If you prefer to stick with native iframes, add loading="lazy":

<iframe
  width="560"
  height="315"
  src={`https://www.youtube.com/embed/${id}`}
  title="YouTube video player"
  frameBorder="0"
  loading="lazy"  // Add this
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowFullScreen
/>

3. Dynamic Import with Next.js

For even better performance, dynamically import your component:

// In RichTextComponents.tsx
import dynamic from 'next/dynamic';
import getYouTubeID from "get-youtube-id";

const YouTubeEmbed = dynamic(() => import('./YouTubeEmbed'), {
  loading: () => <div className="h-[315px] w-[560px] bg-gray-200 animate-pulse" />
});

export const RichTextComponents = {
  types: {
    youtube: ({ value }: any) => {
      const id = getYouTubeID(value.url);
      return id ? <YouTubeEmbed id={id} /> : null;
    },
  },
  // ... rest of your components
};

4. Intersection Observer (Custom Solution)

If you want full control, create a lazy-loading wrapper using Intersection Observer, but the lite-embed library above handles this better.

The react-lite-youtube-embed approach (option 1) will give you the biggest performance boost - it's what most high-performance sites use. It reduces initial load time, improves Lighthouse scores, and provides a better user experience by loading the full iframe only when needed.

Might be best to ask in the nextjs channel as this seems more like a Next.js question, not a Sanity issue.
right
https://web.dev/iframe-lazy-loading/ add loading="lazy" attribute to your iframe article below.

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?