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:
- 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
);
}
- I therefore created a new page.tsx file that implements the dynamic imports logic, The key is using
dynamic
import withssr: 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:
Move Local Storage logic to a client-side component
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:
Use
'use client'
directiveUse dynamic imports with
{ ssr: false }
Add client-side checks (e.g.,
typeof window !== 'undefined'
)