7

The documentation says that I can disable server-side rendering by adding 'use client' to the top of files that need to be rendered only client-side.

However, in practice, I've added this header to every file in the project, and I see that both Layout and Page are being rendered server-side.

I can confirm this with a simple page:

'use client';

export default () => {
  console.log('SERVER RENDER (page)');

  return (
    <div>test</div>
  );
};

I would expect next dev to not output "SERVER RENDER (page)", but it does.

Gajus
  • 69,002
  • 70
  • 275
  • 438
  • 1
    Next.js has an official way to [disable ssr](https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading) for client components. No workaround required. – rantao Jul 07 '23 at 00:39
  • And yet the question has been already viewed 3k times. – Gajus Jul 07 '23 at 01:48

2 Answers2

3

It looks like even if a component is marked 'use client', it will still be pre-rendered.

Client Components enable you to add client-side interactivity to your application. In Next.js, they are prerendered on the server and hydrated on the client. You can think of Client Components as how Next.js 12 and previous versions worked (i.e. the pages/ directory).

https://beta.nextjs.org/docs/rendering/server-and-client-components#client-components

@Nikolai pointed this out correctly, but did not answer how to disable SSR.

However, now that we know that Next 13 behaves the same as 12, we can also apply the same hydration workaround that was used in previous versions.

The TLDR is that you want to wrap your layout in a component that conditionally renders the element based on whether it detects the browser environment, e.g.

const Dynamic = ({ children }: { children: React.ReactNode }) => {
  const [hasMounted, setHasMounted] = useState(false);

  useEffect(() => {
    setHasMounted(true);
  }, []);

  if (!hasMounted) {
    return null;
  }

  return <>{children}</>;
};

export default ({ children }: { children: React.ReactNode }) => {
  return (
    <html lang="en">
      <head />
      <body>
        <Dynamic>{children}</Dynamic>
      </body>
    </html>
  );
};

Obviously, make sure you know what you are doing. This is generally not desired behavior, though there are exceptions.

If you are reading this page, you should also be aware of route segment config:

// 'auto' | 'force-dynamic' | 'error' | 'force-static'
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
// 'auto' | 'default-cache' | 'only-cache' | 'force-cache' | 'force-no-store' | 'default-no-store' | 'only-no-store'
export const fetchCache = 'auto'
// 'nodejs' | 'edge'
export const runtime = 'nodejs'
// 'auto' | 'global' | 'home' | string | string[]
export const preferredRegion = 'auto'
 
export default function MyComponent() {}
Gajus
  • 69,002
  • 70
  • 275
  • 438
  • Could you elaborate a bit more on this answer maybe providing a small example? (I'm new to next and even more to next 13 and I'm not 100% sure about how to replicate what you're proposing) – Barbaldo Mar 07 '23 at 10:40
  • 3
    @Barbaldo OP did post a small example :) Essentially, your app will be rendered on the server once. Then it's sent to the client. If it has to re-render (state/props change), that will happen on the client. That's what "use client" means: to re-render on the client. If you want to disable that first render on the server, you should just return `null` in the component when it's being rendered on the server. Since `useEffect` only runs on the client, you can (ab)use that to render `null` only on the client. Another way might be to check if `typeof winow === "undefined"` and return null if it is – merlindru Apr 30 '23 at 07:44
0

You don't need to disable server-side rendering (SSR), as it's not enabled by default in Next.js.

It pre-renders every page unless instructed otherwise, using either Static Generation or SSR.

  1. Static Generation. The HTML generated at build time and will be reused at every request.
  2. SSR. The HTML is generated on each request.

Next.js uses Static Generation whenever possible.


In your example, SSR doesn't happen. You're seeing the SERVER RENDER (page) message in terminal because you run it in dev (next dev) mode. In dev mode there is no build done, so the pages are generated on the go. You won't see this message in production mode. See this for more details.

Using use client; directive doesn't change the above, it just tells Next.js that a component is a Client Component, which will still be pre-rendered.

Nikolai Kiselev
  • 6,201
  • 2
  • 27
  • 37