1865 字
9 分钟

React 服务端渲染

2026-01-21

React 服务端渲染#

服务端渲染(Server-Side Rendering,简称SSR)是指在服务器端生成HTML,然后将其发送到客户端的技术。与客户端渲染(Client-Side Rendering,简称CSR)相比,服务端渲染具有更好的首屏加载性能和SEO友好性。

1. 服务端渲染的优势#

  • 更好的首屏加载性能:服务器直接生成HTML,客户端无需等待JavaScript加载和执行,首屏加载速度更快。
  • 更好的SEO:搜索引擎爬虫可以直接读取服务器生成的HTML,有利于SEO。
  • 更好的用户体验:用户可以更快地看到页面内容,减少等待时间。
  • 支持无JavaScript环境:在禁用JavaScript的浏览器中,服务端渲染的页面仍然可以正常显示。

2. 服务端渲染的缺点#

  • 服务器负载增加:服务器需要处理HTML生成的工作,增加了服务器的负载。
  • 开发复杂度增加:服务端渲染需要处理前后端代码的兼容性,增加了开发的复杂度。
  • 首字节时间(TTFB)可能增加:服务器需要生成HTML,可能会增加首字节时间。

3. 服务端渲染的实现方法#

3.1 使用Next.js#

Next.js是一个基于React的框架,提供了内置的服务端渲染支持,是实现React服务端渲染的最简单方法。

安装Next.js#
Terminal window
# 使用create-next-app创建项目
npx create-next-app@latest my-app
# 进入项目目录
cd my-app
# 启动开发服务器
npm run dev
创建服务端渲染页面#

在Next.js中,页面默认就是服务端渲染的。

pages/index.js
import React from 'react';
export default function Home() {
return (
<div>
<h1>Welcome to Next.js</h1>
<p>This is a server-side rendered page.</p>
</div>
);
}
使用getServerSideProps#

getServerSideProps是Next.js提供的一个函数,用于在服务器端获取数据并传递给页面组件。

pages/users.js
import React from 'react';
export default function Users({ users }) {
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
// 在服务器端获取数据
export async function getServerSideProps() {
// 从API获取数据
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
// 返回数据作为props
return {
props: { users }
};
}
使用getStaticProps和getStaticPaths#

对于静态内容,Next.js提供了getStaticPropsgetStaticPaths函数,用于在构建时生成静态HTML。

pages/posts/[id].js
import React from 'react';
export default function Post({ post }) {
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
}
// 在构建时获取数据
export async function getStaticProps({ params }) {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
const post = await response.json();
return {
props: { post }
};
}
// 在构建时生成静态路径
export async function getStaticPaths() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await response.json();
const paths = posts.map(post => ({
params: { id: post.id.toString() }
}));
return {
paths,
fallback: false
};
}

3.2 手动实现服务端渲染#

除了使用Next.js,我们也可以手动实现React的服务端渲染。

安装依赖#
Terminal window
npm install express react react-dom
创建服务器#
server.js
const express = require('express');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const App = require('./src/App').default;
const app = express();
// 静态文件服务
app.use(express.static('public'));
// 服务端渲染路由
app.get('*', (req, res) => {
// 渲染React组件为HTML
const html = ReactDOMServer.renderToString(<App />);
// 构建完整的HTML页面
const fullHtml = `
<!DOCTYPE html>
<html>
<head>
<title>React SSR</title>
</head>
<body>
<div id="root">${html}</div>
<script src="/bundle.js"></script>
</body>
</html>
`;
// 发送HTML到客户端
res.send(fullHtml);
});
// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
创建客户端代码#
src/App.js
import React from 'react';
function App() {
return (
<div>
<h1>React Server Side Rendering</h1>
<p>This is a server-side rendered React app.</p>
</div>
);
}
export default App;
// src/client.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 客户端 hydration
ReactDOM.hydrate(<App />, document.getElementById('root'));
配置Webpack#
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/client.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react']
}
}
}
]
}
};
构建和运行#
Terminal window
# 构建客户端代码
npm run build
# 启动服务器
node server.js

4. 服务端渲染的最佳实践#

  1. 使用Next.js:Next.js提供了内置的服务端渲染支持,简化了开发过程,是实现React服务端渲染的首选方案。

  2. 合理使用数据获取方法

    • 对于静态内容,使用getStaticPropsgetStaticPaths,在构建时生成静态HTML。
    • 对于动态内容,使用getServerSideProps,在服务器端获取数据。
    • 对于客户端特定的数据,使用客户端数据获取(如useEffect)。
  3. 优化服务器性能

    • 使用缓存减少重复计算。
    • 优化数据库查询。
    • 使用CDN缓存静态资源。
    • 考虑使用服务器less架构。
  4. 处理错误

    • getServerSidePropsgetStaticProps中处理错误。
    • 使用Error Boundary处理客户端错误。
    • 提供友好的错误页面。
  5. 优化首屏加载

    • 减少首屏的内容大小。
    • 优化CSS和JavaScript的加载。
    • 使用预加载和预连接。
  6. 处理状态管理

    • 对于服务端渲染的应用,需要确保状态在服务器端和客户端之间的一致性。
    • 可以使用Redux、Zustand等状态管理库,并在服务器端初始化状态。
  7. 处理路由

    • 在Next.js中,使用文件系统路由,简化了路由的管理。
    • 对于手动实现的服务端渲染,需要确保服务器端和客户端的路由一致。
  8. 测试服务端渲染

    • 测试服务器端渲染的HTML是否正确。
    • 测试客户端hydration是否正常。
    • 测试不同场景下的性能。

5. 服务端渲染与客户端渲染的结合#

在实际应用中,我们可以结合使用服务端渲染和客户端渲染,根据页面的特点选择合适的渲染方式。

  • 首屏页面:使用服务端渲染,提高首屏加载速度和SEO友好性。
  • 内部页面:使用客户端渲染,减少服务器负载。
  • 静态内容:使用静态生成(SSG),在构建时生成静态HTML。
  • 动态内容:使用服务端渲染(SSR),在服务器端获取数据并生成HTML。

6. 服务端渲染的未来#

随着Web技术的发展,服务端渲染也在不断演进。以下是一些服务端渲染的未来趋势:

  • 边缘渲染:将渲染工作从中心服务器转移到边缘节点,减少延迟,提高性能。
  • 增量静态再生:在构建后,可以通过增量静态再生更新静态页面,结合了静态生成和服务端渲染的优点。
  • React Server Components:React 18引入的新特性,允许在服务器端直接渲染组件,减少客户端JavaScript的大小。

练习#

  1. 使用Next.js创建一个服务端渲染的应用。
  2. 创建一个使用getServerSideProps获取数据的页面。
  3. 创建一个使用getStaticPropsgetStaticPaths生成静态页面的应用。
  4. 手动实现一个React服务端渲染的应用。
  5. 比较服务端渲染和客户端渲染的性能差异。

总结#

在本章节中,我们学习了React服务端渲染的实现方法和最佳实践,包括:

  • 服务端渲染的优势和缺点
  • 使用Next.js实现服务端渲染
  • 手动实现服务端渲染
  • 服务端渲染的最佳实践
  • 服务端渲染与客户端渲染的结合
  • 服务端渲染的未来趋势

服务端渲染是提高React应用性能和SEO友好性的重要技术,特别是对于首屏加载速度和SEO要求较高的应用。通过合理使用服务端渲染,可以显著改善用户体验,提高应用的竞争力。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

React 服务端渲染
https://firefly.cuteleaf.cn/posts/react/10-react-server-side-rendering/
作者
Lireal
发布于
2026-01-21
许可协议
CC BY-NC-SA 4.0

目录