About
server-rendered markup is the dynamic possibility of server-side rendering (vs static).
The steps are:
- the web server returns a web page where the root component has been rendered as HTML with special react data attributes (via the ReactDOMServer.renderToString)
- the react virtual dom tree is build when the react javascript bundle is loaded by te browser via the hydrate function.
Advantages
- Faster page loads: The html is rendered. The page does not need to load the javascript bundle to render.
- SEO purposes: It allow search engines to crawl your pages without Javascript.
The disadvantage is that the architecture is more complicated and you need to take into account where your code will be running (ie on the server or on the browser).
Steps
Server: Html page creation
On the server side, you can use of this two methods to generate HTML with react data attributes:
- ReactDOMServer.renderToString(..) 1) to render a React element to its initial HTML. React will return an HTML string.
- ReactDOMServer.renderToNodeStream(element) 2) - Returns a Readable stream
The below example shows you how to create a page on the server side with the ReactDOMServer.renderToString(..) 3) function.
- The definition of our app with with only one component, the Welcome component created in the getting started page.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const App = <Welcome name="Foo" />;
- The rendering to transform the component in reacted HTML
const toHydrateHtml = ReactDOMServer.renderToString(App);
- The creation of the HTML page where /static/bundle.js is the classic React bundle (see client_bundle) that will start the hydratation (tree building) after loading.
const htmlPage = `
<!doctype html>
<html>
<head>
<title>Dynamic SSR example</title>
</head>
<body>
<div id="root">
<!-- The reacted HTML inside the root div element -->
${toHydrateHtml}
</div>
<!-- The classic bundle (client) that calls the building of the tree with the hydratation when loaded -->
<script src="/static/bundle.js">
</body>
</html>
`;
- If you would be on a server, you would use it like that. Example with a Node HTTP server
// http.createServer(function (req, res) {
// res.writeHead(200, {'Content-Type': 'text/html');
// res.write(htmlPage);
// res.end();
//}).listen(port);
- In our case, we just output it to the console.
console.log(htmlPage.trim());
- Output: The page send will look like that:
Client: Hydratation React bundle
This section shows you how to create the bundle.js file added to the pages created on the server side.
The pages will become active, or hydrated, when the JavaScript bundle has loaded.
The bundle is a classic javascript bundle but:
- instead of calling the ReactDOM.render to create the virtual DOM tree and transform it as HTML
- it will build the virtual DOM tree from the HTML with react attribute of the page. A process called hydration started with the ReactDOM.hydrate() function 4)
The client.js (start point for the bundle.js file) client would looks like (import/export statement excluded)
window.addEventListener("load", () => {
ReactDOM.hydrate(<App />, document.getElementById('root'));
};);
Code Demo
A fully functional demo repository can be found here if you want to take a look.
Library / Tool
Next
A full server framework with own link/image/routing component React Framework - Next.js. Doc
Razzle
A framework that tries to do no more than basic server side rendering and lets you choose all other library (routing/…).
razzle (https://razzlejs.org/docs/how-it-works)
2 configs, 2 ports, 2 webpack instances, both watching and hot reloading the same filesystem, in parallel during development and a little webpack.output.publicPath magic.
Deprecated
Open source is hard…
- https://github.com/redfin/react-server (deprecated)
Rendering Time
There is two moments where you can render:
- at runtime - rendered on the server (the files are created on demand)
- at build_time - rendered at build time (a lot of static files are created)
Runtime
At runtime, means that the node server will render when an HTTP request is made.
Build time
You can render (ie create the pages) at build time which is called prerendering / snapshoting
You don't need a node server.
See Web - Prerendering / Snapshoting (Dynamic to Static Web Site Generation)
Documentation / Reference
- https://github.com/facebook/react/blob/master/fixtures/ssr/README.md - SSR Fixtures - A set of test cases for quickly identifying issues with server-side rendering.