DEV Community

Nadim Chowdhury
Nadim Chowdhury

Posted on

How to Implement Server-Side Rendering (SSR) in a MERN Stack App

Server-Side Rendering (SSR) improves performance, SEO, and the initial load time of web applications by rendering pages on the server before sending them to the client. In a MERN (MongoDB, Express, React, Node.js) stack application, implementing SSR can significantly enhance user experience. In this guide, we’ll walk through the steps to set up SSR in a MERN app.


1. What is Server-Side Rendering (SSR)?

SSR is the process of rendering React components on the server and sending the fully rendered HTML to the client. This differs from Client-Side Rendering (CSR), where JavaScript is executed in the browser to build the UI.

Benefits of SSR:

  • Improved SEO – Search engines can index pre-rendered pages.
  • Faster initial load time – Users see content sooner.
  • Better performance on low-end devices – The server does the heavy lifting.
  • Improved social media sharing – Metadata and Open Graph tags are rendered correctly.

2. Setting Up the MERN Stack for SSR

Step 1: Install Dependencies

You'll need the following dependencies in your MERN app:

npm install express react react-dom @babel/preset-env @babel/preset-react babel-register ignore-styles
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure Babel for Server-Side Compilation

Create a .babelrc file to enable JSX and modern JavaScript features on the server:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}
Enter fullscreen mode Exit fullscreen mode

3. Setting Up Express for SSR

Step 3: Create the Server (server.js)

Set up an Express server to handle SSR.

import express from 'express';
import fs from 'fs';
import path from 'path';
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './src/App';
import { StaticRouter } from 'react-router-dom/server';

const app = express();
const PORT = process.env.PORT || 3000;

// Serve static files
app.use(express.static(path.resolve(__dirname, 'public')));

app.get('*', (req, res) => {
  const context = {};
  const reactMarkup = renderToString(
    <StaticRouter location={req.url} context={context}>
      <App />
    </StaticRouter>
  );

  fs.readFile(path.resolve(__dirname, 'index.html'), 'utf8', (err, data) => {
    if (err) {
      return res.status(500).send("An error occurred");
    }
    return res.send(
      data.replace('<div id="root"></div>', `<div id="root">${reactMarkup}</div>`)
    );
  });
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

4. Modifying React App for SSR

Step 4: Adjust index.html Template

Create an index.html file as a template in your public folder:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MERN SSR App</title>
</head>
<body>
    <div id="root"></div>
    <script src="/bundle.js" defer></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Step 5: Modify React Entry Points

Modify src/index.js to hydrate the server-rendered HTML.

import React from 'react';
import { hydrate } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

hydrate(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

5. Bundling the Client-Side JavaScript

Step 6: Configure Webpack for Client Bundling

Create a webpack.config.js file to bundle React code.

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx']
  }
};
Enter fullscreen mode Exit fullscreen mode

Run Webpack to generate the client-side bundle:

npx webpack --mode=production
Enter fullscreen mode Exit fullscreen mode

6. Deploying the MERN SSR App

Step 7: Deploy to a Cloud Server

  • Use Vercel or Netlify for frontend.
  • Deploy Express backend on Render, DigitalOcean, or AWS.

Conclusion

Implementing SSR in a MERN stack app significantly improves performance, SEO, and user experience. By following these steps, you can ensure that your app loads faster and is indexed better by search engines.

Start integrating SSR today and take your MERN applications to the next level! 🚀

Support My Work ❤️

If you enjoy my content and find it valuable, consider supporting me by buying me a coffee. Your support helps me continue creating and sharing useful resources. Thank you!

Connect with Me 🌍

Let’s stay connected! You can follow me or reach out on these platforms:

🔹 YouTube – Tutorials, insights & tech content

🔹 LinkedIn – Professional updates & networking

🔹 GitHub – My open-source projects & contributions

🔹 Instagram – Behind-the-scenes & personal updates

🔹 X (formerly Twitter) – Quick thoughts & tech discussions

I’d love to hear from you—whether it’s feedback, collaboration ideas, or just a friendly hello!

Disclaimer

This content has been generated with the assistance of AI. While I strive for accuracy and quality, please verify critical information independently.

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →