Skip to content
Dashboard

Guide to fast websites with Next.js: Tips for maximizing server speeds and minimizing client burden

Tinloof Co-founder

Tinloof Co-founder Seif Ghezala gives insights into how his team measures website speed with best practices to make faster websites.

Copy link to headingThe basics of site speed: Measuring data correctly

Vercel Speed Insights

Learn how to get a detailed view of your website's performance metrics to help facilitate informed decisions on optimization.

Get Started

Copy link to headingHow to speed up server response: Make use of Next.js’ rendering toolbox

Copy link to headingWhen possible: Pre-render the entire page

Copy link to headingElse: Partial Prerender

Copy link to headingFinal resort: Render a loading shell while waiting for the final response

Copy link to headingCache fetch requests for fast server responses when using loading spinners

app/page.tsx
export default function Home() {
// The CMS data is guaranteed to be fresh every 2 minutes
const cmsData = await fetch(`https://...`, { next: { revalidate: 120 } });
return <h1>{cmsData.title}</h1>
}

app/page.tsx
export default function Home() {
// The CMS data is cached until the tag is revalidated
const cmsData = await fetch(`https://...`, { next: { tags: ['landing-page']);
return <h1>{cmsData.title}</h1>
}

app/api/revalidate/route.ts
import { revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest): Promise<NextResponse> {
const secret = req.nextUrl.searchParams.get('secret');
const tag = req.nextUrl.searchParams.get('landing-page');
if(!tag || !isValid(secret)) {
return NextResponse.json({ status: 400});
}
return revalidate(tag);
}

Copy link to headingHow to speed up the page render: Minimize client burden

Copy link to headingReduce the JavaScript bundle size and minimize the impact of hydration

Copy link to headingReduce the impact of client components on page speed

Copy link to headingOnly use client components when necessary

Copy link to headingPlace client components in the leaves of the page tree

Copy link to headingBe mindful of third-party dependencies’ bundle sizes

Copy link to headingLazy-load client components when possible

Copy link to headingEfficiently load third-party scripts

Copy link to headingHow to load fonts more efficiently

Copy link to headingHow to load images more efficiently

Copy link to headingHow to load videos more efficiently

import { preload } from "react-dom";
import { unstable_getImgProps as getImgProps } from "next/image";
type Props = {
playbackId: string;
loading: "lazy" | "eager";
resolution: "SD" | "HD";
};
export default function MuxVideo({ playBackId, loading, loading }: Props) {
const mp4Url = `https://stream.mux.com/${playbackId}/${
resolution === "SD" ? "medium" : "high"
}.mp4`;
const webmUrl = `https://stream.mux.com/${playbackId}/${
resolution === "SD" ? "medium" : "high"
}.webm`;
// Use `getImgProps` to convert the video poster image to WebP
const {
props: { src: poster },
} = getImgProps({
src: `https://image.mux.com/${playbackId}/thumbnail.webp?fit_mode=smartcrop&time=0`,
alt: "",
fill: true,
});
// Preload the poster when applicable
if (loading === "eager") {
preload(poster, {
as: "image",
fetchPriority: "high",
});
}
return (
<video
autoPlay
playsInline
loop
controls={false}
muted
preload="none"
>
<source src={mp4Url} type="video/mp4" />
<source src={webmUrl} type="video/webm" />
</video>
);
}

'use client';
import Image from 'next/image';
import { useEffect, useState } from 'react';
import useInView from '~/hooks/useInView';
import Video, { VideoProps } from './Video';
export default function LazyLoadedVideo(props: VideoProps) {
const { ref, inView } = useInView({ triggerOnce: true });
return (
<>
{!inView ? (
<Image
ref={ref as React.RefObject<HTMLImageElement>}
alt={'Video poster'}
src={props.poster ?? ''}
className={props.className}
style={props.style}
loading={'lazy'}
layout="fill"
/>
) : (
<Video {...props} />
)}
</>
);
}

Copy link to headingHow to reduce the HTML document size

Copy link to headingUse virtualization

Copy link to headingHow to speed up user interactions

Copy link to headingThe importance of a performant website

Want to talk to an expert?

Brainstorm with our team about your unique use case of Next.js.

Send us a message

Ready to deploy?