/layout.js @ 1732206458609 [Home]

Disabling Component SSR Server-Side

The above component is a client component that does not trigger the hydration errors - because it never ran on the server! Did you notice how it "popped in"? Reload to see it again - remember, the red outline highlights elements that are dynamically inserted into the DOM. That's because there was no initial html rendered and delivered to the browser. After the page loaded, the Client Component loaded and rendered itself.

The source doesn't use the state tricks in the previous example to ensure that the SSR output matches the CSR output:

ClientComponent.js
'use client'
export default () => <p className={"client-component"}>
  This content is generated client-side. Datestamp: {Date.now()}
</p>

import with next/dynamic

The difference here is that we are importing the component in a different way in our RSC code. We've created a wrapper component around the Client Component that imports it using next/dynamic:

ClientComponentSSRWrapper.js
import dynamic from 'next/dynamic'
const ClientComponent = dynamic(() => import('./ClientComponent'), {
  ssr: false
})
export const ClientComponentNoSSR = ()=><ClientComponent/>

Key Points

  1. next/dynamic is just a composite of React.lazy() and <Suspense>
  2. The second options argument to dynamic() set ssr:false to tell the server to skip this component entirely when rendering html.

Generated HTML

So if the component doesn't SSR, what is put in its place in the generated static html?

If you View Source of this page, you'll see the static html that gets generated in place of where the Client Component will evenually be rendered:

<!--$!--><template data-dgst="DYNAMIC_SERVER_USAGE" data-msg="DYNAMIC_SERVER_USAGE" data-stck=" at ServerComponentWrapper (C:\workspace\demystifying-rsc\node_modules\next\dist\server\app-render\create-server-components-renderer.js:78:31) at InsertedHTML (C:\workspace\demystifying-rsc\node_modules\next\dist\server\app-render\app-render.js:835:33)"></template><!--/$-->

When React reconciles the static html above with the Virtual DOM - which contains a reference to the Client Component - it doesn't generate a hydration error because the above content is a valid placeholder and it knows that a Client Component will go there.

When the Client Component generates its html, that html entirely replaces the content above in the document.

The Virtual DOM for Client-Only Components

The Virtual DOM representation of this page has more content and a few new things, like $Sreact.suspense:

What's going on here?

Let's dig in a little more...

Client Component Details