Home Web Front-end JS Tutorial A Guide to Server-Side Rendering (SSR) with Vite and React.js

A Guide to Server-Side Rendering (SSR) with Vite and React.js

Aug 06, 2024 am 02:35 AM

A Guide to Server-Side Rendering (SSR) with Vite and React.js

Let’s dive deeper into the concept of server-side rendering (SSR) and how it can enhance the user experience of your web application.

The Concept of Server-Side Rendering

When a user visits your website, they typically receive bare HTML initially, which then triggers the loading of additional assets like JavaScript (e.g., App.js) and CSS (e.g., style.css). This traditional approach, often referred to as client-side rendering, means that the user must wait for these resources to download and execute before seeing any meaningful content. This delay can lead to a suboptimal user experience, especially for users on slow connections or devices.

Server-side rendering addresses this issue by sending the user a fully rendered HTML page in response to their initial request. This pre-rendered HTML includes the complete markup, allowing the user to see the content immediately without waiting for JavaScript to load and execute.

The key benefits of SSR include:

  • Reduced Time to Largest Contentful Paint (LCP): The user sees the content much faster because the server sends a complete HTML document.

  • Improved SEO: Search engines can index your content more effectively since the content is readily available in HTML.

  • Better Initial User Experience: Users can start reading and interacting with the content sooner, leading to higher engagement rates.

Balancing Performance Metrics

While SSR can reduce the LCP, it might increase the time of Interaction to Next Paint (INP). This is the time it takes for the user to interact with the page after it has loaded. The goal is to ensure that by the time the user decides to interact with the site, such as clicking a button, the necessary JavaScript has loaded in the background, making the interaction smooth and seamless.

A poor implementation of SSR can lead to a scenario where the user sees content but can't interact with it because the JavaScript hasn’t loaded yet. This can be more frustrating than waiting for the entire page to load initially. Therefore, it's crucial to continuously monitor and measure performance metrics to ensure that SSR is genuinely improving the user experience.

Setting Up SSR in Vite and React.js

We'll break this down into a few steps:

  1. Create a ClientApp Component
  2. Update index.html
  3. Create a ServerApp Component
  4. Set Up the Build Scripts
  5. Configure the Node Server

1. Create a ClientApp Component

We'll start by creating a ClientApp.jsx file, which will handle all the browser-specific functionality.

// ClientApp.jsx
import { hydrateRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
Copy after login

Here, we import hydrateRoot from react-dom/client, BrowserRouter from react-router-dom, and our main App component.

// ClientApp.jsx
// Hydrate the root element with our app
hydrateRoot(document.getElementById('root'), 
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
Copy after login

We use hydrateRoot to render our app on the client side, specifying the root element and wrapping our App with BrowserRouter. This setup ensures all browser-specific code stays here.

Next, we need to modify our App.jsx.

// App.jsx
import React from 'react';

// Exporting the App component
export default function App() {
  return (
    <div>
      <h1>Welcome to My SSR React App!</h1>
    </div>
  );
}
Copy after login

Here, we keep our App component simple for demonstration purposes. We export it so it can be used in both client and server environments.

2. Update index.html

Next, we need to update index.html to load ClientApp.jsx instead of App.jsx and also add the parsing token to split the HTML file in the server, so we can stream the content in the root div.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="./vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"><!--not rendered--></div>
    <script type="module" src="./src/ClientApp.jsx"></script>
  </body>
</html>

Copy after login

3. Create a ServerApp Component

Now, let's create a ServerApp.jsx file to handle the server-side rendering logic.

// ServerApp.jsx
import { renderToPipeableStream } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import App from './App';

// Export a function to render the app
export default function render(url, opts) {
  // Create a stream for server-side rendering
  const stream = renderToPipeableStream(
    <StaticRouter location={url}>
      <App />
    </StaticRouter>,
    opts
  );

  return stream;
}
Copy after login

4. Set Up the Build Scripts

We'll need to update our build scripts in package.json to build both the client and server bundles.

{
  "scripts": {
    "build:client": "tsc vite build --outDir ../dist/client",
    "build:server": "tsc vite build --outDir ../dist/server --ssr ServerApp.jsx",
    "build": "npm run build:client && npm run build:server",
    "start": "node server.js"
  },
  "type": "module"
}
Copy after login

Here, we define separate build scripts for the client and server. The build:client script builds the client bundle, while the build:server script builds the server bundle using ServerApp.jsx. The build script runs both build steps, and the start script runs the server using server.js (which will be created in the next step).

Remove tsc from the client and server build if you are not using TypeScript.

5. Configure the Node Server

Finally, let's configure our Node server in server.js.

// server.js
import express from 'express';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import renderApp from './dist/server/ServerApp.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PORT = process.env.PORT || 3001;

// Read the built HTML file
const html = fs.readFileSync(path.resolve(__dirname, './dist/client/index.html')).toString();
const [head, tail] = html.split('<!--not rendered-->');

const app = express();

// Serve static assets
app.use('/assets', express.static(path.resolve(__dirname, './dist/client/assets')));

// Handle all other routes with server-side rendering
app.use((req, res) => {
  res.write(head);

  const stream = renderApp(req.url, {
    onShellReady() {
      stream.pipe(res);
    },
    onShellError(err) {
      console.error(err);
      res.status(500).send('Internal Server Error');
    },
    onAllReady() {
      res.write(tail);
      res.end();
    },
    onError(err) {
      console.error(err);
    }
  });
});

app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}`);
});

Copy after login

In this file, we set up an Express server to handle static assets and server-side rendering. We read the built index.html file and split it into head and tail parts. When a request is made, we immediately send the head part, then pipe the stream from renderApp to the response, and finally send the tail part once the stream is complete.

By following these steps, we enable server-side rendering in our React application, providing a faster and more responsive user experience. The client receives a fully rendered page initially, and the JavaScript loads in the background, making the app interactive.

Conclusion

By implementing server-side rendering (SSR) in our React application, we can significantly improve the initial load time and provide a better user experience. The steps involved include creating separate components for client and server rendering, updating our build scripts, and configuring an Express server to handle SSR. This setup ensures that users receive a fully rendered HTML page on the first request, while JavaScript loads in the background, making the application interactive seamlessly. This approach not only enhances the perceived performance but also provides a robust foundation for building performant and scalable React applications.

The above is the detailed content of A Guide to Server-Side Rendering (SSR) with Vite and React.js. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

Demystifying JavaScript: What It Does and Why It Matters Demystifying JavaScript: What It Does and Why It Matters Apr 09, 2025 am 12:07 AM

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

Is JavaScript hard to learn? Is JavaScript hard to learn? Apr 03, 2025 am 12:20 AM

Learning JavaScript is not difficult, but it is challenging. 1) Understand basic concepts such as variables, data types, functions, etc. 2) Master asynchronous programming and implement it through event loops. 3) Use DOM operations and Promise to handle asynchronous requests. 4) Avoid common mistakes and use debugging techniques. 5) Optimize performance and follow best practices.

How to achieve parallax scrolling and element animation effects, like Shiseido's official website?
or:
How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? How to achieve parallax scrolling and element animation effects, like Shiseido's official website? or: How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? Apr 04, 2025 pm 05:36 PM

Discussion on the realization of parallax scrolling and element animation effects in this article will explore how to achieve similar to Shiseido official website (https://www.shiseido.co.jp/sb/wonderland/)...

How to merge array elements with the same ID into one object using JavaScript? How to merge array elements with the same ID into one object using JavaScript? Apr 04, 2025 pm 05:09 PM

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

The Evolution of JavaScript: Current Trends and Future Prospects The Evolution of JavaScript: Current Trends and Future Prospects Apr 10, 2025 am 09:33 AM

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

The difference in console.log output result: Why are the two calls different? The difference in console.log output result: Why are the two calls different? Apr 04, 2025 pm 05:12 PM

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...

See all articles