服务器端渲染(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)的过程:
-
服务器发送完全渲染的 HTML。
-
浏览器立即显示 HTML。
-
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
-
设置一个 Next.js 项目
-
创建服务器端渲染的页面
-
让 Next.js 处理完整 HTML 的生成和客户端水合(hydration)
以下是一个简单的 Next.js 示例,使用的是 App Router:
// app/page.jsasync 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 应用时,需要注意以下步骤:
部署流程
-
构建客户端和服务器端的代码包:
-
分别生成前端和后端的独立代码包。
-
运行 SSR 服务器:
-
将服务器作为后台进程运行。
-
使用进程管理工具:
-
使用如 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 秒)。
最佳实践
-
确保使用支持 SSR 或 SSG 的框架(如 Next.js、Nuxt.js 等)。
-
在集成 Builder Pages 或 Sections 时,遵循框架的服务器端数据获取指南。
-
参考
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 请求。
来自:公众号-高级前端进阶,欢迎大家关注!
在线备战面试、刷题指南,拿走不谢,要学会站在别人的肩膀上提升自己点击这里-->
最后:
如果你现在正在找工作,可以私信“web”或者直接添加下方小助理进群领取前端面试小册、简历优化修改、大厂内推以及更多阿里、字节大厂面试真题合集,和p8大佬一起交流。