Speed Up your Nextjs 14 Website

How to speed up your Next.js 14 website easily, and why is it important?

Accelerating Page Speed with Next.js

4 min readApr 5, 2024

--

Page speed is a significant ranking factor for search engines. Next.js offers various features to improve your site’s loading times, including automatic code splitting, optimized image loading with the `next/image` component, and incremental static regeneration (ISR) for updating static content without rebuilding the entire site. These features not only enhance your SEO but also significantly improve the user experience, leading to higher engagement and conversion rates.

Next.js offers all that we need to speed up our website. Since images have a big impact on Web Core Vitals like LCP, etc. we start with the image delivery.

Here is the GitHub link -> https://github.com/cloudapp-dev/nextjs14-SEO and the link to the final result as a spoiler-> https://nextjs14-seo.vercel.app/

Default next.config.js

Next.js 14 as a default uses the Webp format for the image if we use the built-in native “next/image” package. Let’s add the Avif format as well in our next.config.js file. As you can see we withlisted the domain “images.ctfassets.net” because we are using Contentful as a CMS in our example.

/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
formats: ["image/avif", "image/webp"],
remotePatterns: [
{
protocol: "https",
hostname: "images.ctfassets.net",
pathname: "**",
},
],
},
};

module.exports = nextConfig;

Image formats/size: A Key to SEO Success

With the majority of web traffic coming from mobile devices, ensuring your Next.js site is mobile-friendly is non-negotiable. Responsive design, fast loading times, and touch-friendly navigation are crucial elements. Next.js’s built-in features support these requirements, making it simpler to create a website that performs well on both desktop and mobile platforms.

Let’s take a look at the main component for image delivery in our example which you can find under src/components/contentful/CtfPicture.component.tsx

We use the new “getImageProps” introduced with Next.js 14 to enable the usage of the srcset / picture tag.

import NextImage, { ImageProps as NextImageProps } from "next/image";
import { getImageProps } from "next/image";
import { twMerge } from "tailwind-merge";

import { ImageFieldsFragment } from "@/lib/__generated/sdk";

interface ImageProps extends Omit<ImageFieldsFragment, "__typename"> {
nextImageProps?: Omit<NextImageProps, "src" | "alt">;
}

export const CtfPicture = ({
url,
width,
height,
title,
nextImageProps,
}: ImageProps) => {
if (!url || !width || !height) return null;

// common option
const common_high = {
alt: title || "",
width: width,
height: height,
priority: nextImageProps?.priority,
className: twMerge(nextImageProps?.className, "transition-all"),
};
const common_medium = {
alt: title || "",
width: 800,
height: 500,
className: twMerge(nextImageProps?.className, "transition-all"),
};

const common_low = {
alt: title || "",
width: 300,
height: 200,
className: twMerge(nextImageProps?.className, "transition-all"),
};

// Pass common as an argument with src in getImageProps and destructure the output.
const {
props: { srcSet: high },
} = getImageProps({
...common_high,
src: url,
priority: nextImageProps?.priority,
});

const {
props: { srcSet: medium },
} = getImageProps({
...common_medium,
src: url,
priority: nextImageProps?.priority,
});

const {
props: { srcSet: low, ...rest },
} = getImageProps({
...common_low,
src: url,
priority: nextImageProps?.priority,
});

return (
<picture>
<source media="(max-width: 740px)" srcSet={low} />
<source media="(max-width: 980px)" srcSet={low} />
<source media="(min-width: 1280px)" srcSet={medium} />
<source media="(min-width: 1480px)" srcSet={high} />
<img alt={title || ""} {...rest} />
</picture>
);
};

The component is called from the ArticleHero.tsx under src/components/contentful/

<div className="flex-1 basis-1/2">
{article.featuredImage && (
<CtfPicture
nextImageProps={{
className: "w-full",
priority: true,
sizes: undefined,
}}
{...article.featuredImage}
/>
)}
</div>

Defining “srcset’s” for the picture tag

We define three different srcSet with different sizes and use them in combination with the media-query. Depending on the max-width we use different srcSet and therefore different image dimensions. The browser can select the best fit.

return (
<picture>
<source media="(max-width: 740px)" srcSet={low} />
<source media="(max-width: 980px)" srcSet={low} />
<source media="(min-width: 1280px)" srcSet={medium} />
<source media="(min-width: 1480px)" srcSet={high} />
<img alt={title || ""} {...rest} />
</picture>
);

As a reference, you will find the component CtfImage.component.tsx as well in the project because it showcases the image handling that I used in my previous Next.js 13.5 projects.

How to reproduce it

Clone my repo -> https://github.com/cloudapp-dev/nextjs14-SEO

Create a Free Contentful account following my post -> https://www.cloudapp.dev/nextjs-complete-example-typescript-app-router-contentful

After setting up the right values in the .env.local file you can launch the command

npm i -> to install all packages
npm run cf-import -> which will use the provided export.json file to push the data to your new contentful account
npm run dev -> start dev server to show the result under http://localhost:3000

Conclusion: Next.js as a Catalyst for SEO Success

Next.js stands out as a powerful framework for building SEO-friendly websites. By following best practices for on-page optimization, site structure, page speed, mobile optimization, and content creation, you can leverage Next.js to significantly improve your website’s search engine rankings.

Cloudapp-dev

Thank you for reading until the end. Before you go:

  • Please consider clapping and following the writer! 👏
  • Visit cloudapp.dev to find out more about how we are supporting the dev community around the world.

--

--

Cloudapp-dev

Developer and tech/cloud enthusiast, who believes in Knowledge Sharing - Free Tutorials (https://www.cloudapp.dev)