首页  >  文章  >  web前端  >  使用 Vite 和 React.js 进行服务器端渲染 (SSR) 指南

使用 Vite 和 React.js 进行服务器端渲染 (SSR) 指南

王林
王林原创
2024-08-06 02:35:32765浏览

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

让我们更深入地了解服务器端渲染 (SSR) 的概念以及它如何增强 Web 应用程序的用户体验。

服务器端渲染的概念

当用户访问您的网站时,他们通常最初会收到裸 HTML,然后触发加载其他资源,例如 JavaScript(例如 App.js)和 CSS(例如 style.css)。这种传统方法通常称为客户端渲染,意味着用户必须等待这些资源下载并执行才能看到任何有意义的内容。这种延迟可能会导致用户体验不佳,尤其是对于连接速度或设备较慢的用户而言。

服务器端渲染通过向用户发送完全渲染的 HTML 页面来响应其初始请求来解决此问题。此预渲染的 HTML 包含完整的标记,允许用户立即查看内容,而无需等待 JavaScript 加载和执行。

SSR 的主要优势包括:

  • 减少最大内容绘制 (LCP) 的时间:用户可以更快地看到内容,因为服务器发送完整的 HTML 文档。

  • 改进的 SEO:搜索引擎可以更有效地索引您的内容,因为内容可以轻松以 HTML 格式获取。

  • 更好的初始用户体验:用户可以更快地开始阅读内容并与内容互动,从而提高参与率。

平衡绩效指标

虽然 SSR 可以减少 LCP,但它可能会增加 与下一次绘制的交互 (INP) 的时间。这是页面加载后用户与页面交互所需的时间。目标是确保当用户决定与网站交互时(例如单击按钮),必要的 JavaScript 已在后台加载,从而使交互流畅且无缝。

SSR 的糟糕实现可能会导致用户看到内容但无法与其交互,因为 JavaScript 尚未加载。这可能比等待整个页面最初加载更令人沮丧。因此,持续监控和测量性能指标以确保 SSR 真正改善用户体验至关重要。

在 Vite 和 React.js 中设置 SSR

我们会将其分解为几个步骤:

  1. 创建 ClientApp 组件
  2. 更新index.html
  3. 创建 ServerApp 组件
  4. 设置构建脚本
  5. 配置节点服务器

1. 创建ClientApp组件

我们首先创建一个 ClientApp.jsx 文件,它将处理所有特定于浏览器的功能。

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

在这里,我们从react-dom/client 导入HydraRoot,从react-router-dom 导入BrowserRouter,以及我们的主要App 组件。

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

我们使用 HydroRoot 在客户端渲染我们的应用程序,指定根元素并使用 BrowserRouter 包装我们的应用程序。此设置可确保所有特定于浏览器的代码都保留在此处。

接下来,我们需要修改我们的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>
  );
}

在这里,为了演示目的,我们保持应用程序组件简单。我们将其导出,以便它可以在客户端和服务器环境中使用。

2.更新index.html

接下来,我们需要更新index.html以加载ClientApp.jsx而不是App.jsx,并添加解析令牌以拆分服务器中的HTML文件,以便我们可以流式传输根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>

3. 创建ServerApp组件

现在,让我们创建一个 ServerApp.jsx 文件来处理服务器端渲染逻辑。

// 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;
}

4. 设置构建脚本

我们需要更新 package.json 中的构建脚本来构建客户端和服务器包。

{
  "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"
}

在这里,我们为客户端和服务器定义单独的构建脚本。 build:client 脚本构建客户端捆绑包,而 build:server 脚本使用 ServerApp.jsx 构建服务器捆绑包。构建脚本运行两个构建步骤,启动脚本使用 server.js(将在下一步中创建)运行服务器。

如果您不使用 TypeScript,请从客户端和服务器版本中删除 tsc。

5. 配置节点服务器

最后,让我们在 server.js 中配置我们的 Node 服务器。

// 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.

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.

以上是使用 Vite 和 React.js 进行服务器端渲染 (SSR) 指南的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn