MalcMind

How to Disable NextJs from pre-Rendering a page

tirelesscodingnight.jpg
this image was created by a Bing prompt: "someone trying to prerender a page through a tireless night"

Why Prerender

NextJs is great because when you first navigate to a page on a Server or Client component it will generate a non interactive preview of the page, then it hydrates the JavaScript portions.

That is great for SEO and quick page loads, however it can sometimes cause problems at build time.

Stoping NextJS Build Errors

NextJS has three Rendering Strategies - Static Rendering(Default), Dynamic Rendering, and Streaming.

Sometimes we need to a force a Server Side page to render only at request time(dynamic rendering) - or else we might get pre-rendering errors caused by rendering certain assets..

In this case we get this error when our SSR component tries to render in too early and fails from our <App /> client component which contains a useRef() dependency that relies on global self(which only exists in browsers):

This SSR code fails:

import Container from '@mui/material/Container';
import Hero from '../../Components/Hero'
import App from './App.js';

export default function FiringRange() {
  return (
    <Container maxWidth="xl"  >
       <Hero contentNeeded = {"Hacker Firing Range"}/>
        <App />
    </Container>
  )
}

Our App component contains a child component which returns a terminalRef:

return <div ref={terminalRef} />; // this is returned within a child of our App Component

We get this error:

ReferenceError: self is not defined at 68329 (/vercel/path0/.next/server/chunks/3510.js:1:299) at __webpack_require__ (/vercel/path0/.next/server/webpack-runtime.js:1:161) at 91477 (/vercel/path0/.next/server/app/(main site)/(Landing Pages)/FiringRange/page.js:1:2205)

The issue:

Nextjs will immediately show a fast non-interactive initial preview of the client route.which in this case is causing the render to fail because its trying to incorrectly generate the useRef (which will fail without the browser present). We must stop the prerender by using Dynamic rendering instead of static rendering.

Method 1:

Special functions such as cookies()[1] , headers()[2], and searchParams*[3] prop will force the server component to render dynamically

[1] Headers and cookies only work with 'use client' [2][3] Don't let this confuse you but params will not force it to render dynamically just searchParams

import Container from '@mui/material/Container';
import Hero from '../../Components/Hero'
import App from './App.js';
import { headers } from 'next/headers' // this prevents ssr

export default function FiringRange() {
  const headersList = headers() //prevents ssr
  const referer = headersList.get('referer')  //prevents ssr

  return (
    <Container maxWidth="xl"  >
       <Hero contentNeeded = {"Hacker Firing Range"}/>
        <App />
    </Container>
  )
}```
Note: You also need to instantiate the function. Simply importing it wont convert it to a dynamic route. Also in Nextjs 15 + headers is a promise that you must await

```JSX
 const headersList = await headers() //prevents ssr

If you want to force it into dynamic mode using the searchParams prop you must also call the prop for it to work

export default async function CreateANewBlog({searchParams}) {

const filters = (await searchParams)

Method 2:

We can use the [next/dynamic import] to deop a component out of SSR prerendering.

import Container from '@mui/material/Container';
import Hero from '../../Components/Hero'
import dynamic from 'next/dynamic'

const App = dynamic(() => import('./App.js'), { ssr: false })

export default function FiringRange() {
  return (
    <Container maxWidth="xl"  >
        <Hero contentNeeded = {"Hacker Firing Range"}/>
        <App />
    </Container>
  )
}

Note: that this method will only work on "use client" components

Method 3:

If your on a page that needs to be made dynamic itself you can force the option by exporting a const dynamic variable that nextJs will figure out at runtime:

export const dynamic = 'force-dynamic'
// 'auto' | 'force-dynamic' | 'error' | 'force-static'

Note: this will only work on "use client" components. If you want you server component to render correctly at build time be sure to export const dynamic in all the use client components that your server component imports.

reference: https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config

Resources

NextJs sources:

Similar Issues: