Optimizing YouTube embed performance in Sanity with React Portable Text
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;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:
1. Lazy Load with react-lite-youtube-embed (Recommended)
The best solution is to use a facade/lite embed approach. Install react-lite-youtube-embed:
npm install react-lite-youtube-embedThen 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.
Show original thread3 replies
Was this answer helpful?
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.