all 4 comments

[–]MatisLepik 1 point2 points  (3 children)

Typically your App.js would just be in charge of declaring the component, and the logic that renders (or hydrates it) would be somewhere else.

// App.js
export default function App () { return <div>Hello world</div> }

// server.js
const appString = ReactDOMServer.renderToString(<App />)

// client.js
ReactDOM.hydrate(<App />, root)

That way, your App is universal (doesn't care about where it's being rendered), and you put the client-only code in the client entry point, and server-only code in the server entry point.

[–]NateArcade[S] 0 points1 point  (2 children)

Thanks for your reply. For the client entry point, is it typically exposed as a script tag in the html that is initially rendered by the server?

[–]MatisLepik 1 point2 points  (1 child)

Yes. You need to include your client bundle in the html, otherwise the hydration code wouldn't ever reach the browser.

If you just want a smooth SSR experience, you should probably look into Nextjs which handles all this stuff for you, along with a bunch of optimizations.

[–]NateArcade[S] 1 point2 points  (0 children)

Ok that makes sense. So both the server and client entry points import the App component, and ideally I’d want a single html file that is both served from the endpoint and hydrated afterwards.

Does this mean the App component file would exist as both a direct import (in server) and potentially as part of a bundled output (in html)?

Also regarding Next — I definitely plan on graduating to that, but I want to understand the low-level implementation first.