编程笔记

lifelong learning & practice makes perfect

翻译|服务器端渲染(SSR):打造更出色的 Web 应用

服务器端渲染(SSR)已经存在了一段时间,但仍然值得我们深入探讨。这项技术可以让你的应用更快、对搜索引擎更友好。在本指南中,我们将解释什么是 SSR,为什么你可能想要使用它,以及如何在不让你抓狂的情况下实现它。我们将涵盖基础知识,将其与客户端渲染进行比较,并讨论一些实际示例。

什么是服务器端渲染?

从根本上说,SSR 是关于在服务器上渲染你的网页,而不是在浏览器中。当用户请求一个页面时,服务器会完成所有繁重的工作,并将一个完全渲染的页面发送给客户端。然后,客户端的 JavaScript 接管,使其具有交互性。服务器在厨房里做准备工作,而浏览器只需将菜端上桌。
以下是一个最小的 Express.js 示例:

SSR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const express = require('express');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const App = require('./App');

const app = express();

app.get('/', (req, res) => {
const html = ReactDOMServer.renderToString(<App />);
res.send(`
<!DOCTYPE html>
<html>
<body>
<div id="root">${html}</div>
<script src="client.js"></script>
</body>
</html>
`);
});

app.listen(3000, () => console.log('Server running on port 3000'));

从服务器到浏览器,完全渲染的页面

当我们谈论 SSR 交付“完全渲染的页面”时,理解其真正含义非常重要。让我们来分解一下:

什么是完全渲染的页面?

完全渲染的页面是一个包含用户首次加载页面时会获得的所有内容的 HTML 文档。这包括:

  • 完整的 DOM 结构
  • 所有文本内容
  • 图像占位符和其他媒体元素
  • 初始样式

以下是一个基本示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<title>My SSR Page</title>
<style>
/* Initial styles */
</style>
</head>
<body>
<header>
<h1>Welcome to My Site</h1>
<nav><!-- Fully populated navigation --></nav>
</header>
<main>
<article>
<h2>Article Title</h2>
<p>This is the full content of the article...</p>
</article>
</main>
<footer><!-- Fully populated footer --></footer>
<script src="hydration.js"></script>
</body>
</html>

与客户端渲染(CSR)的区别

相比之下,一个客户端渲染(CSR)的初始 HTML 可能如下所示:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<title>My CSR Page</title>
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>

CSR 页面完全依赖 JavaScript 来填充内容。

完全渲染的 HTML 的好处

  • 更快的初始绘制:浏览器可以立即开始渲染内容。
  • 更好的 SEO:搜索引擎可以读取所有内容,而无需执行 JavaScript。
  • 改进的可访问性:屏幕阅读器和其他辅助技术可以立即访问内容。
  • 韧性:即使 JavaScript 加载失败,基本内容仍然可用。

The hydration process

在发送完全渲染的 HTML 之后,SSR 应用程序通常会经历一个称为 hydration 的过程:

  • 服务器发送完全渲染的 HTML。
  • 浏览器立即显示此 HTML。
  • JavaScript 加载并 hydrates 页面,添加交互性。
    以下是一个简化的 React 水合示例:
    1
    2
    3
    4
    5
    6
    // Simplified React hydration example
    import { hydrateRoot } from 'react-dom/client';
    import App from './App';

    const domNode = document.getElementById('root');
    hydrateRoot(domNode, <App />);
    这个过程允许快速的初始加载,同时仍然提供现代 Web 应用的丰富交互性。
    请记住,虽然 SSR 提供了这些完全渲染的页面,但它并非没有权衡。服务器的工作量更大,你需要在服务器和客户端之间小心处理状态。然而,对于许多应用来说,完全渲染页面的好处使 SSR 成为一个有吸引力的选择。

CSR 和 SSR 有什么区别?

客户端渲染(CSR)和服务器端渲染(SSR)是渲染网页的两种不同方法。以下是它们的主要区别:

客户端渲染(CSR)

  1. 服务器发送一个包含 JavaScript 包的最小 HTML 文件。
  2. 浏览器下载并运行 JavaScript。
  3. JavaScript 创建页面内容并使其具有交互性。

    优点:

  • 初始加载后平滑的交互
  • 需要更少的服务器资源

    缺点:

  • 较慢的初始页面加载
  • 潜在的 SEO 挑战

服务器端渲染(SSR)

  1. 服务器创建完整的 HTML 内容。
  2. 浏览器快速接收并显示预渲染的 HTML。
  3. 然后加载 JavaScript 以使页面完全具有交互性。

    优点:

  • 更快的初始页面加载
  • 更适合 SEO
  • 在较慢的设备上表现良好

    缺点:

  • 设置可能更复杂
  • 可能使用更多的服务器资源

CSR VS SSR

从本质上讲,CSR更多地在浏览器中工作,而SSR更多地在服务器上工作。它们之间的选择取决于项目的特定需求,平衡因素,如初始加载时间,SEO要求和服务器资源。

SSR 和搜索引擎:HTTP 中的完美匹配

服务器端渲染可以对搜索引擎如何看待你的网站产生重大影响。让我们来分解一下:

更快的索引

搜索引擎机器人是没有耐心的。它们希望立即看到你的内容。使用 SSR,当机器人来敲门时,你的页面已经准备好了——不需要等待 JavaScript 加载和渲染。

内容一致性

SSR 确保搜索引擎看到与用户相同的内容。使用客户端渲染,总是存在机器人可能错过一些动态加载内容的风险。

改进的加载时间

搜索引擎喜欢快速的网站。SSR 可以显著减少初始加载时间,这可能在排名中给你带来一些优势。

移动优先索引

随着谷歌的移动优先索引,SSR 在较慢的移动连接上的性能优势变得更加重要。

预览

虽然严格来说不是搜索引擎功能,但 SSR 使在社交平台上共享内容时生成准确的预览变得更加容易。这可以通过增加参与度和反向链接来间接提升你的 SEO。
SSR 是 SEO 的强大工具,但它不是唯一因素。内容质量、相关性和整体用户体验在搜索引擎排名中至关重要。SSR 只是确保搜索引擎可以有效地抓取和索引你的内容,潜在地在可见性和性能指标上给你带来优势。

如何实际实现 SSR

实现 SSR 并不需要很复杂。让我们来看看如何使用 Next.js(一个流行的 React 框架,使 SSR 变得简单)来实现它:

  1. 设置一个 Next.js 项目。
  2. 创建服务器端渲染的页面。
  3. 让 Next.js 处理完全渲染的 HTML 和客户端水合。

以下是一个使用 App Router 的简单 Next.js 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// app/page.js
async function getData() {
const res = await fetch('<https://api.example.com/data>')
if (!res.ok) {
throw new Error('Failed to fetch data')
}
return res.json()
}

export default async function Home() {
const data = await getData()

return <h1>Hello {data.name}</h1>
}

在这个示例中:

  1. Home 组件是一个异步函数,允许服务器端数据获取。
  2. getData() 获取我们需要的数据。
  3. 组件直接渲染数据。

Next.js 自动处理 SSR 过程:

  1. 当请求进来时,Next.js 在服务器上运行这个组件。
  2. 它等待数据被获取。
  3. 它使用获取的数据渲染组件。
  4. 完全渲染的 HTML 被发送到客户端。
  5. 一旦浏览器中加载了 JavaScript,页面就变得具有交互性。

这种方法让你在不需要手动设置服务器或管理渲染过程的情况下获得 SSR 的好处。

更高级的 SSR 解决方案

如果你不想重新发明轮子,有几个框架可以为你处理 SSR 的复杂性。以下是不同生态系统中流行选项

选项

参考

欢迎关注我的其它发布渠道