SSR VS CSR in Next.js

SSR VS CSR in Next.js

This blog comes out as a result of a build error I experienced when server-side rendering was being done on my sign-up component, My component had a browser API (web storage API - Local storage)

I got a build error because SSR cannot go through for components dependent on browser environments. Next.js tries to pre-render pages on the server.

NOTE: Next.js utilizes the hybrid approach of CSR and SSR.

Under normal circumstances, I would have checked if I was on the client’s side:

if (typeof window !== 'undefined') {
  // Safe to use localStorage here
}

I had another solution in mind. These could maintain my code readability by introducing another important factor: modularity. Ladies and gentlemen, I am talking about dynamic imports with Next.js.

Dynamic imports with Next.js prevent server-side rendering for components that rely on browser APIs like Local Storage:

Here is how the simple implementation took effect:

  1. I renamed my current page.tsx component to CareGiverSignupClient.tsx, this is to be my client-side component.
'use client';

import React from 'react';

export default function CareGiverSignupClient() {
  // Your existing localStorage-dependent code goes here
  const userData = localStorage.getItem('userData');

  return (
    // Your existing component JSX
  );
}
  1. I therefore created a new page.tsx file that implements the dynamic imports logic, The key is using dynamic import with ssr: false to ensure the component only renders in the browser.
import dynamic from 'next/dynamic';

const CareGiverSignupWithLocalStorage = dynamic(
  () => import('./CareGiverSignupClient'), 
  { ssr: false }
);

export default function CareGiverSignupPage() {
  return <CareGiverSignupWithLocalStorage />;
}

This approach helped me to:

  1. Move Local Storage logic to a client-side component

  2. Prevents server-side rendering errors

Why does next do SSR pre-rendering to client components?

Next.js uses Server-Side Rendering (SSR) by default for performance and SEO benefits. Even for client components, Next.js attempts to pre-render pages during build time. This means it tries to generate static HTML for components, which can cause issues with browser-only APIs like localStorage.

The key reasons for this behavior are:

  • Improved initial page load performance

  • Better search engine optimization

  • Rendering initial content faster

For components that rely on browser-specific APIs, you need to:

  1. Use 'use client' directive

  2. Use dynamic imports with { ssr: false }

  3. Add client-side checks (e.g., typeof window !== 'undefined')