关于 SSR,我承认我之前只是“会用”而已

news2026/4/9 5:11:44
SSR、Hydration 这些词在 Web 前端领域非常常见开发者经常能接触到这个概念。但是这些是什么为什么怎么用过去我都没有深究下去关于 SSR我承认我之前只是“会用”而已。一、区分 CSR 还是 SSR回顾自己做的一些小玩意发现自己大部分都是用 Vite React TS 来构建项目是 CSR采用的是 SPA 场景Vite 默认是 SPA。虽说也用 Next.js 写过项目属于 SSR 支持但没有深究过里面的内容。如何区分启动项目以后检查页面源代码SSR会看到完整的内容而不是空的div idrootCSR浏览器几乎拿到的就是空的 HTML特性SPASSR首屏速度慢等 JS 下载执行快直接返回 HTML页面切换极快局部刷新较慢可能重新请求SEO差好服务器压力小只传数据大需要渲染页面复杂度低高典型场景后台系统、工具类应用博客、电商、内容型网站什么场景适合 SSR 内容型 C 端产品电商、资讯、博客需要 SEO 和首屏速度比较适合强交互的后台系统、内部工具就没必要硬上 SSR 了。核心判断标准很简单首屏速度和 SEO 对业务价值有多大如果答案是“不大”SSR 就是过度设计。SEO搜索引擎优化是一种让网站在搜索引擎结果中更加清晰也帮助我们将搜索结果更靠前的过程。搜索引擎爬取网页跟随页面之间的链接并索引找到的内容。搜索时搜索引擎会显示索引内容。爬行者遵守规则。如果你在为网站进行搜索引擎优化时密切关注这些规则则会为网站提供最好的机会以便在首批结果中显示增加流量和可能的收入用于电子商务和广告。二、为什么用 Next.js “没感觉”我觉得搭建一个脚手架用 Next.js 实现 SSR 确实是没有难度的。框架本身封装了很多方法用起来比较傻瓜写代码的方式和写普通 React SPA 几乎一样所以我“没感觉”所以 Next.js 的使用没有很深刻的体会。Next.js 框架保护了我这样的猪头。它作为框架把 SSR 的工程化难题全解决了开箱即用。从设计哲学的角度来说Next.js是非常成功了。又也许是因为自己的 toy 项目没感到 SSR 的好处——体量都比较小没有太深的感受反而觉得有点重并不是太好用。SSR 的特点是什么SSR 的代表框架有 React 生态的 Next.js 和 Vue 生态的 Nuxt。它的优点是首屏加载快用户能很快看到内容同时 SEO 友好搜索引擎可以直接抓取到完整的 HTML缺点也很明显服务器压力更大因为每次请求都要重新渲染页面而且整体复杂度高需要处理水合Hydration、DOM 结构匹配等一系列问题。按照这些特点来看之前我的猜想是有道理的。toy项目没有必要SSR自然也就感受不到。那么SSR 的真正价值场景是什么呢SSR 常应用在首屏依赖大量异步数据比如电商详情页、资讯详情页、SEO 直接决定业务流量C 端内容产品、弱网环境下 HTML 比 JSONJS 更早到达的情况下。而我的小项目SEO 无所谓首屏慢 0.5 秒也没人投诉。这种场景强行上 SSR反而是用复杂度换不存在的问题。框架无好坏场景才决定选择。渲染模式其实是一个光谱不是简单的二选一。从纯静态 HTML 到 SSG、ISR、SSR、流式 SSR、CSR再到部分水合、群岛架构中间有很多种组合也就衍生到一个混合渲染的概念这在现代框架中其实是常见的。现代趋势混合方案现在很多框架Next.js、Nuxt允许按页面或按组件选择不需要 SEO 的后台页面 → 用 SPA 模式需要首屏快、SEO 好的营销页/博客 → 用 SSR 模式这就是所谓的混合渲染。例如 Next.js 的use client一开始我以为是“只在客户端运行”的意思。但它其实是水合边界的声明不是运行环境的切换——只有你显式标记的组件才会被水合。标记了use client的组件服务端照样会执行一次来生成 HTML只是客户端需要再次激活。所以它并不解决服务端没有window的问题你依然要用useEffect或动态导入来绕过。再看 Next.js 的 App Router它默认就是 React Server Components连 JS 都不发给客户端只有显式标记use client的组件才会被水合。这种“部分水合”的思路其实更接近 Astro 的群岛架构。三、SSR 到底是怎么工作的简单说流程是用户访问 → 服务器在服务端就把组件渲染成完整 HTML → 浏览器直接看到完整页面 → 再下载 JS 补充交互 Hydration水合。如果用 React 官方的底层 API 来理解核心就是renderToString或者更高级的renderToPipeableStream流式 SSR。服务端把App /变成 HTML 字符串浏览器拿到后先展示再用hydrateRoot把事件绑上去。把组件变成 HTML这一步其实和 React 在浏览器里做的事一模一样只是运行的地方不同。浏览器里CSR组件代码 → React 计算虚拟 DOM → 变成真实 DOM → 挂到 div idroot 里服务器上SSR组件代码 → React 计算虚拟 DOM → 变成 HTML 字符串 → 直接拼到响应里返回服务器上不需要挂载 DOM只需要输出字符串。React 提供了专门的 API 来做这件事renderToString()把一个组件变成 HTML 字符串renderToPipeableStream()流式输出边渲染边发送所以“在服务端把组件渲染成完整 HTML”这句话底层就是调了renderToString(App /)。hydrateRoot的作用已经有了 HTML 了服务端生成的现在 JS 加载完了React 需要在浏览器里接管这个页面。如果不做任何事页面看起来是好的但按钮点不了输入框没反应——因为事件监听器还没绑上去。如果用传统的renderReact 会把现有的 DOM 全部删掉重新创建一份再把事件绑上去。这样效率低而且用户可能会看到页面闪烁。hydrateRoot的做法检查现有的 DOM 结构不删除、不重建直接在已有的 DOM 节点上挂载事件监听器把内部状态初始化好打个比方你收到了一辆已经组装好的车服务端给的 HTML技师hydrateRoot不需要把车拆了重装只需要把方向盘、刹车、油门这些操控装置接上车就能开了。This will hydrate the server HTML inside the browser DOM node with the React component for your app. Usually, you will do it once at startup. If you use a framework, it might do this behind the scenes for you.这样可以将浏览器 DOM 节点内的服务器 HTML 与应用的 React 组件进行水合。通常你会在启动时做一次。如果你用框架它可能在幕后帮你做到这一点。To hydrate your app, React will “attach” your components’ logic to the initial generated HTML from the server. Hydration turns the initial HTML snapshot from the server into a fully interactive app that runs in the browser.为了给你的应用提供水合React 会把组件的逻辑“附加”到服务器最初生成的 HTML 上。Hydration 将服务器上的初始 HTML 快照转化为一个在浏览器中运行的完全交互式应用。这里只是介绍了一下react 框架对于 ssr的做法更多细节还是具体结合项目代码或者源码。建议读一读各个框架关于 SSR Hydration的官方介绍文档。hydrateRoot – 反应 — hydrateRoot – React服务器端渲染 (SSR) | Vue.js 框架Getting Started: Server and Client Components | Next.js用最简单的代码对比纯 CSR与SSR Hydration纯 CSRimport{createRoot}fromreact-dom/clientimportAppfrom./App// 创建一个新的根节点从头渲染constrootcreateRoot(document.getElementById(root))root.render(App/)SSR Hydrationimport{hydrateRoot}fromreact-dom/clientimportAppfrom./App// 不创建新节点而是复用已有的 HTMLhydrateRoot(document.getElementById(root),App/)区别就这一行createRoot→hydrateRoot其他代码一模一样。写到这里发现没感觉的真相自然水落石出——框架把这一切都隐藏了。用 Next.js 的时候不需要手动调用renderToString不需要手动调用hydrateRoot只管写组件框架帮你做了。这也就是我之前说的“框架保护了我这样的猪头”——好处是省事坏处是不知道底层发生了什么。React的最小示例server.jsimportexpressfromexpressimport{renderToString}fromreact-dom/serverimportAppfrom./App.jsxconstappexpress()app.get(/,(req,res){consthtmlrenderToString(App/)res.send(!DOCTYPE html html body div idroot${html}/div script src/client.js/script /body /html)})app.listen(3000)client.jsimport{hydrateRoot}fromreact-dom/clientimportAppfrom./App.jsxhydrateRoot(document.getElementById(root),App/)页面是服务端生成的右键查看源代码能看到完整内容水合成功后页面可以交互如果 App 组件里写了Date.now()会报水合错误看到第三点也许会有疑问了为什么会报错误呢接下来就说说水合。四、关于 Hydration水合1. 服务端生成静态骨架 (Server-Side Rendering)动作当用户访问页面时服务器会快速获取数据将你的框架代码如 React、Vue渲染成一段完整的 HTML 字符串。结果用户浏览器接收到的是立即可见的完整 HTML 页面解决了传统 SPA 应用“白屏”和 SEO 难的问题。2. 客户端注入灵魂与交互 (Hydration)动作浏览器显示 HTML 后会加载 JS 文件。框架如 React 的hydrateRoot开始工作它不会重新创建整个 DOM那样会浪费性能而是找到现有的 DOM 节点在上面挂载事件监听器如onClick和绑定内部状态。结果原本“静态”的页面瞬间“活”了变成了一个可点击、可交互的完整单页应用SPA。一个生动的比喻水合就像给一辆已经组装好的顶级跑车静态 HTML安装发动机和方向盘JS 逻辑。你在展厅里第一眼就能看到它炫酷的外形快速首屏但只有技师把操控系统装进去后你才能真正点火开走它。一开始我以为水合就是给 DOM 挂上事件监听器后来发现没那么简单。水合时 React 到底在比什么不是比内容文本而是比 DOM 树结构。服务端生成的 HTML 结构必须和客户端第一次 render 生成的虚拟 DOM 结构完全一致。如果不一致React 会直接报错Text content did not match。更麻烦的后果水合失败后React 不会尝试修复而是直接丢弃服务端渲染的 HTML在客户端重新渲染整棵子树。降级为 CSR 行为。这意味着你付出了 SSR 的成本服务端渲染 网络传输却没有得到首屏收益甚至比纯 CSR 更慢。常见的水合失败场景代码级// ❌ 危险时间戳不一致functionBadComponent(){returndiv{Date.now()}/div}// ❌ 危险条件判断不一致functionBadComponent(){returndiv{typeofwindowobject?客户端:服务端}/div}// ✅ 安全把依赖浏览器的逻辑放到 useEffectfunctionGoodComponent(){const[timestamp,setTimestamp]useState(null)useEffect(()setTimestamp(Date.now()),[])returndiv{timestamp}/div}React 18 的选择性水合新版本支持用Suspense包裹组件优先激活用户正在交互的部分而不是等全部水合完成。这对大型页面很实用。五、Modern.js 与新生态了解 SSR 原理后我们来看看新一代框架是如何优化这个过程的。前段时间才发现字节 2021 年开源的 Modern.js 框架。可以列表对比一下这两个框架。技术Next.jsModern.js打包工具Webpack / TurbopackRspack (基于 Rust速度更快)转译工具Babel / SWCSWC 默认路由自研App Router / Pages RouterReact Router 7 约定式路由服务端框架自研Hono.js轻量高性能本人在构建了许多许多次 Express 框架以后才认识到 Express 确实比较老了但对于新手学习成本低生态也传统而稳定。我最近才了解到 Hono、Bun 等较新的生态更多构建工具相关的 Rsbuild、Rspack 等内容对我来说全是新的值得学一学拓展一下知识面。RspackWebpack 的 Rust 替代品API 兼容但构建速度快很多。解决大型项目 Webpack 构建慢的痛点。目前生态还不够成熟插件支持不如 Webpack。Hono轻量级 Web 框架跨运行时原生 Promise 支持。比 Express 更适合现代 JavaScript 生态。这些“新东西”解决了什么问题我发现一个规律从 Webpack 到 Rspack从 Express 到 Hono本质都是用编译型语言Rust/Go重写 JS 工具链。这不是卷也许也是哈哈哈是因为 JS 做构建工具已经到天花板了——单线程、动态类型、运行时开销大。Rspack 用 Rust 实现多线程并行编译在大型项目上构建速度能提升 5-10 倍。Hono 比 Express 强在哪跨运行时Node、Deno、Bun、Cloudflare Workers 都能跑原生 Promise 支持TypeScript 一等公民。Express 设计于 2010 年那时候还没有async/await异步中间件的处理方式现在看起来确实有点别扭。Modern.js 的定位它更像一个“全家桶”方案不仅仅是 SSR 框架还内置了 BFF 一体化、国际化、Monorepo 支持等。和 Next.js 的“轻核心 社区生态”走的是两条路。字节内部大规模验证过国内场景优化比如 Ant Design 按需加载做得更细致。六、小结回过头看SSR 和 CSR 没有绝对的好坏更多是场景驱动的选择。Next.js 让我“无感”恰恰说明它封装得足够好而 Express 虽老却依然适合新手入门。技术世界变化很快新生态、新框架、新概念总是日新月异。但好奇心永远是最好的导航。这些新东西不需要全都学但了解它们解决了什么问题或许能帮我们在合适的场景做出更好的选择。限于个人写作文中若有疏漏还请不吝赐教。参考文档React SSR 水合Hydration详解SEO - MDN Web 文档术语表Web 相关术语的定义 | MDNhydrateRoot – 反应 — hydrateRoot – React服务器端渲染 (SSR) | Vue.js 框架Getting Started: Server and Client Components | Next.js

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2498375.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…