How I improved PageSpeed score with NextJS

Problem
I had a page with a banner image and two third-party libraries: the Remark42 (comment engine) and React Player (YouTube). As a result, the PageSpeed performance score was quite low, around 50-60. After some research, I was able to improve the score to 99-100. You can view the actual PageSpeed score here.
Solutions
The full code is at GitHub.
-
Load the player only when the user clicks the play button
I used a banner image with a play SVG icon to mimic a video player. When users click on it, React Player loads, and the video plays automatically.
I used the
useState
to keep track of the video playing status:const [isPlaying, setIsPlaying] = useState(false) const hasVideo = blog.attributes.mediaUrl
And I used Next.js Image with placeholder and blurDataURL to further optimize performance:
{hasVideo && !isPlaying ? ( <div className="relative aspect-video w-full overflow-hidden rounded-md bg-gray-900"> <Image className="h-full w-full object-cover" src={blog.attributes.seo.metaImage.data.attributes.url} alt={blog.attributes.seo.metaImage.data.attributes.caption} width={blog.attributes.seo.metaImage.data.attributes.width} height={ blog.attributes.seo.metaImage.data.attributes.height } priority={true} loading="eager" placeholder="blur" blurDataURL={BLUR_IMAGE} /> {/* Play Button Overlay */} <button onClick={() => setIsPlaying(true)} className="absolute inset-0 flex items-center justify-center bg-black/50 transition hover:cursor-pointer hover:bg-black/30" aria-label="Play Video" > <PlayCircleIcon className="h-20 w-20 text-white drop-shadow-lg" /> </button> </div> ) : ( // Load ReactPlayer when user clicks play isPlaying && ( <div className="player-wrapper"> <ReactPlayer className="react-player" url={blog.attributes.mediaUrl} width="100%" height="100%" controls={true} playing={true} muted={false} /> </div> ) )}
-
Load the comment library only when necessary
The ideal time to load Remark42 is when users scroll to the bottom of the page where the comments section is located. This prevents the script from loading when the page initially opens.
I added a
div
element at the end of the page where the comments should appear and used it as a trigger to load Remark42 only when it becomes visible.const [showComments, setShowComments] = useState(false) const commentTriggerRef = useRef<HTMLDivElement | null>(null)
<div ref={commentTriggerRef} className="relative"> <div aria-hidden="true" className="absolute inset-0 flex items-center" > <div className="w-full border-t border-zinc-600" /> </div> </div>
Then, I used the
useEffect
hook to set up an Intersection Observer, which lazily loads Remark42 when thecommentTriggerRef
becomes visible.useEffect(() => { const observer = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting) { setShowComments(true) } }, { threshold: 1.0 }, ) if (commentTriggerRef.current) { observer.observe(commentTriggerRef.current) } return () => { if (commentTriggerRef.current) { observer.unobserve(commentTriggerRef.current) } } }, [])
And finally, render the actual comments at the end:
{showComments && ( <CommentBox location={`${process.env.NEXT_PUBLIC_SITE_URL}/blog/${blog.attributes.slug}`} /> )}
Conclusion
With these simple solutions, you can significantly enhance your website's performance and improve the user experience.