Open In App

Detecting server vs client in NextJS application

Next.js, a popular React framework, helps you to build powerful web applications with ease. However, managing server-side and client-side execution can pose unique challenges. In this article, we'll explore techniques for detecting server or client execution in Next.js applications.

What is Server Side Rendering?

Server-side rendering (SSR) is a technique used to deliver HTML content to a client's browser by pre-rendering it on the server. This approach helps reduce the load on the client's browser and improves page loading times, resulting in faster access to web pages. A quick way to verify if an application is using SSR is to disable JavaScript in the client's browser. If the requested page still loads with content, it indicates that server-side rendering is being employed.

What is Client Side Rendering?

Client-side rendering (CSR) is a method in which all webpage files, such as HTML, CSS, and JavaScript, are delivered to the client's browser. The browser then processes these files locally to render the content on the webpage, requesting resources from the server as needed. This approach shifts the computational load to the client's browser, potentially resulting in slower initial page loading times but allowing for more dynamic and interactive user experiences.

Detecting server vs client-side rendering

Detecting whether Next.js applications are running on the server side or the client side is indeed an essential task to avoid unnecessary hydration errors in our application. Hydration errors occur when there is a mismatch between the server-rendered content and the content rendered on the client side. Knowing whether the application is running on the client or server side is crucial for preventing such errors.

Steps to create a nextJS application

Step 1: Create a nextJS app

Run the following command and configure as shown in figure below to setup nextJS app.

 npx create-next-app demo
next

creating nextJS app

Step 2: Start nextJS demo app

navigate to the created folder and run the application using following commands.

cd demo

If in case any error in creation check the dependencies and scripts below if any mismatch incase. use latest version if not update to latest one. use following command to update nextJS version.

npm install next@latest

Step 3: Access your application

For accessing your application visit http://localhost:3000

Approach 1: Using typeof window

Since window object is only available on the client side, you can use typeof window to check if it's defined. If it's undefined, the code is running on the server side.

Example:

//index.js

import Head from "next/head";

export default function Home() {
    if (typeof window == "undefined") {
        console.log("Application is on server side");
    } else {
        alert("Application is on client side");
    }

    return (
        <>
            <Head>
                <title>Create Next App</title>
            </Head>
            <main>
                <h2>This is a demo page</h2>
            </main>
        </>
    );
}

Output:

output

server side output

clientside

client side output

Approach 2: Using process.browser

Next.js provides a built-in variable process.browser which is true on the client side and false on the server side.

Example:

//index.js

import Head from "next/head";

export default function Home() {
    if (process.browser) {
        console.log("Variant 2: Application is on client side");
    } else {
        console.log("Variant 2: Application is on server side");
    }

    return (
        <>
            <Head>
                <title>Create Next App</title>
            </Head>
            <main>
                <h2>This is a demo page</h2>
            </main>
        </>
    );
}

Output:

output

using process.browser

Approach 3: Using a custom flag

You can set a custom flag during the server-side render and check for its presence on the client side.

Example:

//index.js

import Head from "next/head";
import { useEffect, useState } from "react";

export default function Home() {
    const [isServer, setIsServer] = useState(true);

    useEffect(() => {
        setIsServer(false);
    }, []);

    if (isServer) {
        console.log("Custom Flag: Application is on server side");
    } else {
        console.log("Custom Flag: Application is on client side");
    }

    return (
        <>
            <Head>
                <title>Create Next App</title>
            </Head>
            <main>
                <h2>This is a demo page</h2>
            </main>
        </>
    );
}

Output:

output

server side otput

clientside

client side

Approach 4: Using req object in getServerSideProps

In server-side rendering methods like getServerSideProps, you have access to the req object. If req is defined, it signifies that the code is executing on the server side. Since getServerSideProps exclusively operates on the server, any code within it will not be executed on the client side. Therefore, the else part meant for client-side execution will not be triggered.

Example:

//index.js

import Head from "next/head";

export default function Home({ isServer }) {
    if (isServer) {
        console.log("Application is on server side");
    }
    return (
        <>
            <Head>
                <title>Create Next App</title>
            </Head>
            <main>
                <h2>This is a demo page</h2>
            </main>
        </>
    );
}

export async function getServerSideProps(context) {
    return {
        props: {
            isServer: !!context.req,
        },
    };
}

Output:

output

output using obj req in getServerSideProps

Approach 5: Using window object inside useEffect

If you're using React hooks, you can utilize the useEffect hook and check for the window object. This method is particularly suitable for functional components. Since the useEffect hook is part of React, it executes on the client side after the component mounts. Therefore, if you simply need to determine if the code is running on the client side, this approach works well. For instance, it's useful for generating a random number without encountering server-side errors.

Example:

//index.js

import Head from "next/head";
import { useEffect } from "react";

export default function Home() {
    useEffect(() => {
        if (typeof window == "undefined") {
            console.log("Variant 1: Application is on server side");
        } else {
            alert("Variant 1: Application is on client side");
        }
    }, []);

    return (
        <>
            <Head>
                <title>Create Next App</title>
            </Head>
            <main>
                <h2>This is a demo page</h2>
            </main>
        </>
    );
}

Output:

clientside

client side output.

Conclusion

In summary, detecting server vs client-side rendering in Next.js is essential for managing hydration errors and optimizing performance. Methods like checking typeof window, process.browser, custom flags, req object in getServerSideProps, and useEffect with the window object offer versatile approaches. By selecting the appropriate method based on specific requirements, developers can ensure seamless execution and enhance the user experience in Next.js applications.

Article Tags :