一问彻底说清楚SSR渲染

哈喽大家好,我是Fine。今天这篇文章带大家了解一下SSR渲染。
以下是正文:

服务器端渲染(Server-side rendering,简称 SSR)已经存在了一段时间,但值得深入了解。这种技术可以让你的网页应用更快,同时更具 SEO 友好性。

在本指南中,我们将解释什么是 SSR、为什么你可能需要使用它,以及如何轻松实现它。我们会覆盖基础知识,比较 SSR 和客户端渲染(CSR),并讨论一些实际案例。

什么是服务器端渲染?

从本质上讲,服务器端渲染是指在服务器上渲染网页,而不是在浏览器中。当用户请求一个页面时,服务器负责完成渲染工作并将一个完全渲染好的页面发送到客户端,然后客户端的 JavaScript 接管并添加交互功能。

这就像是在厨房里由服务员完成准备工作,浏览器只需要将菜品摆盘上桌。

下面是一个最小化的 Express.js 示例:

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 结构

  • 所有文本内容

  • 图片占位符和其他媒体元素

  • 初始样式

下面是一个基本示例:

<!DOCTYPE html>
<html>
<head>
<title>My SSR Page</title>
<style>
/* 初始样式 */
</style>
</head>
<body>
<header>
<h1>Welcome to My Site</h1>
<nav><!-- 完整的导航内容 --></nav>
</header>
<main>
<article>
<h2>文章标题</h2>
<p>这是文章的完整内容...</p>
</article>
</main>
<footer><!-- 完整的页脚内容 --></footer>
<script src="hydration.js"></script>
</body>
</html>

CSR 的对比

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

<!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 加载失败,基本内容仍然可用。


水合过程

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

  1. 服务器发送完全渲染的 HTML。

  2. 浏览器立即显示 HTML。

  3. JavaScript 加载并“水合”页面,添加交互功能。

以下是一个简化的 React 水合示例:

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)
  • 工作方式:

    • 服务器仅发送一个包含 JavaScript 包的最小 HTML 文件。

    • 浏览器下载并执行 JavaScript。

    • JavaScript 负责创建页面内容并使其具有交互性。

  • 优点:

    • 初次加载后,交互更加流畅。

    • 对服务器资源的需求较少。

  • 缺点:

    • 初始页面加载较慢。

    • SEO 优化存在一定挑战。


服务器端渲染 (SSR)
  • 工作方式:

    • 服务器生成完整的 HTML 内容。

    • 浏览器快速接收并显示预渲染的 HTML。

    • JavaScript 加载后为页面添加交互性。

  • 优点:

    • 初始页面加载速度更快。

    • 更适合搜索引擎优化 (SEO)。

    • 在性能较弱的设备上表现良好。

  • 缺点:

    • 配置较为复杂。

    • 可能需要更多服务器资源。


简单的对比图
  • CSR: 渲染工作主要在浏览器完成。

  • SSR: 渲染工作主要在服务器完成。


    选择 CSR 或 SSR 取决于项目的具体需求,需要平衡初始加载时间、SEO 需求和服务器资源等因素。


SSR 与搜索引擎:天作之合

1. 更快的索引速度

搜索引擎爬虫希望立即获取内容。SSR 在请求到达时生成完整页面,无需等待 JavaScript 加载和渲染,大幅提升内容的可见性。

2. 内容一致性

SSR 确保搜索引擎看到的内容与用户看到的一致,而 CSR 中动态加载的内容可能会被爬虫忽略。

3. 提升加载速度

搜索引擎偏爱快速加载的网站。SSR 减少了初始加载时间,有助于提高排名。

// 搜索引擎排名伪代码
function calculateRanking(site) {
let score = site.relevance;
if (site.loadTime < FAST_THRESHOLD) {
score += SPEED_BONUS;
}
return score;
}
4. 移动优先索引

随着 Google 的移动优先索引策略,SSR 在移动端缓慢连接中的性能优势显得尤为重要。

5. 社交媒体预览

虽然不是搜索引擎的直接功能,SSR 在生成准确社交媒体预览时表现出色,这能间接提高参与度和反向链接,从而提升 SEO。

<!-- SSR 可以轻松添加准确的 meta 标签 -->
<meta property="og:title" content="你的动态标题">
<meta property="og:description" content="你的动态描述">

尽管 SSR 是提升 SEO 的强大工具,但它并非万能良药。内容质量、相关性和用户体验在搜索引擎排名中同样至关重要。SSR 的作用是确保搜索引擎高效抓取和索引内容,为网站的可见性和性能指标提供潜在优势。

如何实现服务器端渲染(SSR)

实现 SSR 并不一定很复杂。以下是使用 Next.js 实现 SSR 的方法,这是一款流行的 React 框架,让 SSR 变得简单易行:


使用 Next.js 实现 SSR

  1. 设置一个 Next.js 项目

  2. 创建服务器端渲染的页面

  3. 让 Next.js 处理完整 HTML 的生成和客户端水合(hydration)

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

// 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>
}
示例解析
  • 异步组件:
    Home 是一个异步函数组件,支持服务器端数据获取。

  • 数据获取:
    getData() 函数用于从 API 获取所需数据。

  • 直接渲染:
    组件直接使用获取到的数据进行渲染。

Next.js SSR 过程
  • 当有请求到来时,Next.js 在服务器上运行该组件。

  • 等待数据获取完成后,渲染组件并生成完整的 HTML。

  • 将完全渲染的 HTML 发送到客户端。

  • 浏览器加载 JavaScript 后,页面变得交互式。

这种方法提供了 SSR 的所有好处,无需手动设置服务器或管理渲染过程。


更高级的 SSR 解决方案

如果不想从头实现 SSR,可以选择使用一些专门处理 SSR 的框架。这些框架简化了复杂性,同时提供额外的功能。以下是一些主流选项:

React
  • Next.js: 最流行的 React 框架,内置 SSR 支持。

  • Remix: 一个全栈 Web 框架,基于 React Router 构建。

  • Gatsby: 主要是静态网站生成器,但也支持 SSR。

Vue
  • Nuxt.js: Vue 应用的首选框架,支持 SSR。

Angular
  • Angular Universal: Angular 的官方 SSR 解决方案。

Svelte
  • SvelteKit: Svelte 的官方应用框架,支持 SSR。

框架无关的 JavaScript
  • Astro: 允许使用多种框架,并支持 SSR。

  • Qwik: 新兴框架,针对性能优化,内置 SSR 支持。

PHP
  • Laravel: 通过 Inertia.js 或 Livewire 组件实现 SSR。

Ruby
  • Ruby on Rails: 通过 Stimulus Reflex 或 Hotwire 实现 SSR。

Python
  • Django: 可使用 Django-Unicorn 或 HTMX 库实现 SSR。

  • Flask: 配合扩展(如 Flask-SSE)也可以实现 SSR。


不同框架提供了各自的 SSR 实现,通常还附带静态站点生成(SSG)、API 路由等功能。选择哪种框架取决于:

  • 你的编程语言偏好

  • 使用的技术生态系统

  • 项目具体需求

通过这些工具,你可以快速构建高性能、SEO 友好的应用程序,而无需深陷 SSR 的复杂细节中。

部署与缓存

在部署 SSR 应用时,需要注意以下步骤:

部署流程
  1. 构建客户端和服务器端的代码包:

    • 分别生成前端和后端的独立代码包。

  2. 运行 SSR 服务器:

    • 将服务器作为后台进程运行。

  3. 使用进程管理工具:

    • 使用如 PM2 或 Supervisor 等工具来确保服务器持续运行。

以下是一个基本的部署流程图:


别忘了缓存!
  • 对服务器渲染的页面进行缓存可以显著降低服务器负载。

  • 通过智能缓存策略加速页面加载,减轻后端压力。


使用 Builder.io 进行 SSR

Builder.io 提供对服务器端渲染 (SSR) 和静态站点生成 (SSG) 的支持,兼容所有组件和框架。这种开箱即用的功能让你无需额外设置即可享受 SSR 和 SSG 的优势。

核心特点
  • 框架无关: 支持多种框架,兼容 SSR 和 SSG。

  • 自动优化: 提供性能优化,包括代码拆分与非屏幕组件的延迟加载。

  • 动态渲染: 可基于用户属性或 A/B 测试渲染不同内容,同时保持 SEO 优势。

  • 轻松集成: 提供 SDK 和文档,便于在现有项目中无缝集成。


实现示例

以下是一个使用 Builder.io 和 Next.js 的示例,展示如何在服务器端获取并渲染内容:

import { builder, BuilderComponent } from '@builder.io/react'

builder.init('YOUR_API_KEY')

export async function getStaticProps({ params }) {
const page = await builder
.get('page', {
userAttributes: {
urlPath: '/' + (params?.page?.join('/') || '')
}
})
.toPromise()

return {
props: {
page: page || null,
},
revalidate: 5, // 每 5 秒重新验证缓存
}
}

export default function Page({ page }) {
return (
<BuilderComponent
model="page"
content={page}
/>
)
}
示例解析
  • API 初始化: 使用 builder.init 初始化 API 密钥。

  • 数据获取: getStaticProps 在构建时或重新验证时获取页面内容。

  • 动态渲染: 基于用户属性动态渲染内容。

  • 缓存控制: 使用 revalidate 设置重新验证周期(如每 5 秒)。


最佳实践
  1. 确保使用支持 SSR 或 SSG 的框架(如 Next.js、Nuxt.js 等)。

  2. 在集成 Builder Pages 或 Sections 时,遵循框架的服务器端数据获取指南。

  3. 参考 getAsyncProps 文档获取更多关于服务器端数据处理的信息。

通过使用 Builder.io 进行 SSR,可以将无头 CMS 的灵活性与服务器端渲染的性能优势相结合,同时保持直观的可视化编辑体验。

总结

服务器端渲染(SSR)是一种强大的 Web 开发技术,能够显著提升应用的性能、SEO 和用户体验。在本文中,我们探讨了 SSR 的定义、与客户端渲染的区别、对搜索引擎的影响,以及如何使用像 Next.js 这样的流行框架进行实践。

我们还讨论了完全渲染页面的概念,并分析了跨不同生态系统的多种 SSR 解决方案。尽管 SSR 具有诸多优势,但在决定是否实施时,务必根据项目的具体需求权衡利弊。


常见问题解答

Q: SSR 会对开发流程产生什么影响?

A: SSR 会使开发变得更复杂,因为需要同时考虑服务器端和客户端环境。你可能需要调整构建流程,并谨慎使用浏览器特定的 API。

Q: SSR 会如何影响网站的可交互时间(TTI)?

A: SSR 能改善初始内容的可见性,但由于浏览器在接收初始 HTML 后仍需加载并水合(hydrate)JavaScript,TTI 可能会略微延迟。

Q: SSR 是否有特定的安全考虑?

A: 是的。使用 SSR 时,需要更加小心不要在服务器端暴露敏感数据或 API。始终对用户输入进行清理,并谨慎处理初始渲染中包含的数据。

Q: SSR 如何处理身份验证和个性化内容?

A: SSR 可以处理身份验证,但需要仔细设计。你可能需要实现如 JWT 令牌或服务器端会话等技术,以管理带身份验证的 SSR 请求。


文章来源:公众号-涅槃快乐  
侵删


   “分享、点赞在看” 支持一波👍