Approfondissons le concept de rendu côté serveur (SSR) et comment il peut améliorer l'expérience utilisateur de votre application Web.
Lorsqu'un utilisateur visite votre site Web, il reçoit généralement initialement du HTML pur, ce qui déclenche ensuite le chargement d'actifs supplémentaires tels que JavaScript (par exemple, App.js) et CSS (par exemple, style.css). Cette approche traditionnelle, souvent appelée rendu côté client, signifie que l'utilisateur doit attendre que ces ressources soient téléchargées et exécutées avant de voir un contenu significatif. Ce délai peut conduire à une expérience utilisateur sous-optimale, en particulier pour les utilisateurs disposant de connexions ou d'appareils lents.
LeRendu côté serveur résout ce problème en envoyant à l'utilisateur une page HTML entièrement rendue en réponse à sa demande initiale. Ce code HTML pré-rendu inclut le balisage complet, permettant à l'utilisateur de voir le contenu immédiatement sans attendre le chargement et l'exécution de JavaScript.
Les principaux avantages de la RSS sont les suivants :
Délai réduit pour la plus grande peinture de contenu (LCP) : L'utilisateur voit le contenu beaucoup plus rapidement car le serveur envoie un document HTML complet.
Référencement amélioré : les moteurs de recherche peuvent indexer votre contenu plus efficacement puisque le contenu est facilement disponible en HTML.
Meilleure expérience utilisateur initiale : les utilisateurs peuvent commencer à lire et à interagir avec le contenu plus tôt, ce qui entraîne des taux d'engagement plus élevés.
Bien que SSR puisse réduire le LCP, il peut augmenter le temps d'Interaction avec la peinture suivante (INP). Il s'agit du temps nécessaire à l'utilisateur pour interagir avec la page après son chargement. L'objectif est de garantir qu'au moment où l'utilisateur décide d'interagir avec le site, par exemple en cliquant sur un bouton, le JavaScript nécessaire est chargé en arrière-plan, rendant l'interaction fluide et transparente.
Une mauvaise implémentation de SSR peut conduire à un scénario dans lequel l'utilisateur voit le contenu mais ne peut pas interagir avec lui car le JavaScript n'est pas encore chargé. Cela peut être plus frustrant que d’attendre que la page entière se charge initialement. Par conséquent, il est crucial de surveiller et de mesurer en permanence les indicateurs de performance pour garantir que la SSR améliore véritablement l'expérience utilisateur.
Nous allons décomposer cela en quelques étapes :
Nous allons commencer par créer un fichier ClientApp.jsx, qui gérera toutes les fonctionnalités spécifiques au navigateur.
// ClientApp.jsx import { hydrateRoot } from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import App from './App';
Ici, nous importons hydrateRoot depuis réagir-dom/client, BrowserRouter depuis réagir-router-dom et notre composant principal d'application.
// ClientApp.jsx // Hydrate the root element with our app hydrateRoot(document.getElementById('root'), <BrowserRouter> <App /> </BrowserRouter> );
Nous utilisons hydrateRoot pour restituer notre application côté client, en spécifiant l'élément racine et en encapsulant notre application avec BrowserRouter. Cette configuration garantit que tout le code spécifique au navigateur reste ici.
Ensuite, nous devons modifier notre 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> ); }
Ici, nous gardons notre composant App simple à des fins de démonstration. Nous l'exportons afin qu'il puisse être utilisé à la fois dans des environnements client et serveur.
Ensuite, nous devons mettre à jour index.html pour charger ClientApp.jsx au lieu d'App.jsx et également ajouter le jeton d'analyse pour diviser le fichier HTML sur le serveur, afin que nous puissions diffuser le contenu dans le div racine.
<!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>
Maintenant, créons un fichier ServerApp.jsx pour gérer la logique de rendu côté serveur.
// 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; }
Nous devrons mettre à jour nos scripts de build dans package.json pour créer à la fois les bundles client et serveur.
{ "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" }
Ici, nous définissons des scripts de build distincts pour le client et le serveur. Le script build:client crée le bundle client, tandis que le script build:server crée le bundle serveur à l'aide de ServerApp.jsx. Le script de construction exécute les deux étapes de construction et le script de démarrage exécute le serveur à l'aide de server.js (qui sera créé à l'étape suivante).
∴ Supprimez tsc de la version client et serveur si vous n'utilisez pas TypeScript.
Enfin, configurons notre serveur Node dans 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}`); });
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.
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.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!