Server-Side Rendering (SSR) is a powerful technique where a web application's HTML is rendered on the server, instead of being rendered on the client side (browser). This approach has many benefits, especially in terms of improving SEO, page load performance, and providing a better user experience for users on slower devices.In this chapter, we will cover SSR from the basics to advanced concepts, giving you a deep dive into SSR with Node.js and providing practical examples.
Basic Concept: In traditional client-side rendering (CSR), a web application renders HTML dynamically in the browser using JavaScript frameworks like React or Vue. However, this approach means that search engines may struggle to index the content since it’s rendered dynamically, and the first-time page load can be slower for users.
How SSR Solves This: SSR allows the server to generate the complete HTML for a page before sending it to the client. This means:
SSR with Node.js: Node.js is often used for SSR because of its ability to handle asynchronous operations efficiently. By using Node.js, you can integrate SSR into your JavaScript stack, making it easy to share code between the server and the client.
In SSR:
User -> Requests a page -> Server processes the request -> Server renders HTML -> HTML sent to user -> Browser displays HTML
SSR improves search engine indexing because the full HTML content is delivered to the crawler, making it easier for bots to index the page properly. This is especially important for content-heavy applications like blogs or e-commerce websites.
Since the server renders the page HTML before sending it, the user can see the content almost immediately, improving perceived performance.
On slower devices or with limited network bandwidth, users get content quickly, and the application becomes interactive as JavaScript loads.
One common use case for SSR is rendering React components on the server using Node.js. This section explains how to set up SSR with a Node.js and React application.
First, create a new Node.js project and install the required packages:
npm init -y
npm install express react react-dom react-dom/server
In this example, we will render a basic React component using Node.js and send the rendered HTML to the client.
// server.js
const express = require('express');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
// Define a basic React component
const App = () => {
return React.createElement('div', null, 'Hello from Server-Side Rendering with Node.js!');
};
// Initialize Express server
const app = express();
app.get('/', (req, res) => {
// Render the React component to an HTML string
const html = ReactDOMServer.renderToString(React.createElement(App));
// Send the complete HTML to the client
res.send(`
SSR Example
${html}
`);
});
app.listen(3000, () => {
console.log('Server is listening on port 3000');
});
express
: We use Express to create a simple server.ReactDOMServer.renderToString()
: This function converts the React component into an HTML string on the server./
) is accessed.
node server.js
Open the browser at http://localhost:3000
to see the rendered React component. Here, the entire HTML for the React component is served by the Node.js server.
After the HTML is rendered and sent to the client, React takes over on the client side and attaches event listeners, enabling interactive features. This process is called “hydration”.
To enable hydration, you would typically serve a JavaScript bundle along with the HTML.
In the server.js
, include a bundle.js
file that will run on the client side to hydrate the React component.
Modify the server-side App.js
to include the hydrate
method for client-side hydration:
import { hydrate } from 'react-dom';
import App from './App';
// Hydrate the component in the client
hydrate( , document.getElementById('root'));
This ensures that React will take over once the HTML is loaded in the browser, making the page interactive.
One challenge of SSR is fetching data before rendering a page. This can be handled by fetching data on the server before rendering the React component.
// server.js
app.get('/data', async (req, res) => {
const data = await fetchDataFromAPI();
const html = ReactDOMServer.renderToString( );
res.send(`
SSR with Data
${html}
`);
});
In this example, the fetchDataFromAPI()
function is used to fetch data from an API before rendering the component. The data is passed to the React component as a prop, and the rendered HTML is returned to the client.
Instead of sending the full HTML once it’s ready, you can stream HTML as it is generated, reducing the Time to First Byte (TTFB). React has support for streaming SSR using renderToPipeableStream
.
const { renderToPipeableStream } = require('react-dom/server');
app.get('/', (req, res) => {
const stream = renderToPipeableStream( , {
onShellReady() {
res.status(200);
stream.pipe(res);
},
});
});
Server-Side Rendering (SSR) with Node.js enhances React applications by improving performance, SEO, and user experience, especially on slower networks or devices. By using SSR techniques, developers can deliver faster, more efficient applications that are easier for search engines to crawl and index.In this chapter, we explored SSR from the basics to advanced concepts such as streaming and data-fetching techniques. Understanding these concepts allows you to build high-performance web applications with React and Node.js. Happy coding !❤️