客户端渲染和服务端渲染#
客户端渲染:(CSR: Client side render ),主要是通过浏览器来渲染页面,浏览器解析 HTML、CSS、JavaScript 文件,然后通过计算布局和渲染页面。
服务器渲染:(SSR: Server side render),服务器生成 HTML 代码,然后把代码发送到浏览器中直接渲染页面。
实现原理#
同构#
- 同构:在服务端中执行一遍代码,然后在客户端又执行一遍代码。
- 服务端渲染通过虚拟 DOM 渲染出
html字符串发送给浏览器,加快页面渲染速度,同时有利于搜索引擎爬虫抓取页面。 - 客户端渲染则处理服务端渲染不能处理的真实 DOM 的相关问题(事件绑定等)。
- 服务端和客户端渲染出一致的内容时使用
hydrate渲染。
路由匹配#
- 服务端渲染使用
StaticRouter路由组件,该组件有 2 个非常重要的属性,属性location可以定位路由。属性context具有通信功能,传入的值会转存为一个名为staticContext的对象,可以在组件里对其赋值,在服务端完成字符串渲染后可以获取到所赋的值。 - react-router-config 库的
matchRoutes方法匹配多级路由,renderRoutes方法渲染多级路由,路由需要改造成配置类型(键值对类型)。 - 页面跳转后,
StaticRouter定位到跳转后路径的组件,服务端渲染该组件成字符串。 - 服务端渲染比客户端渲染更快,不能等到客户端解析 JS 后再去请求数据,需要提前请求数据。
数据处理#
- 服务端渲染前调用组件的
loadData方法提前获取到数据并渲染到字符串中。 - 注水:服务端还将获取的数据注入到
script标签中。 - 脱水:客户端直接从
script标签中获取数据,而不用等到解析 JS 后再请求获取数据,加快页面渲染速度,也防止页面跳白。 - 页面没有第一时间加载而是跳转过来的时候还是需要客户端渲染请求数据。
中间件代理#
1.Node.js不但可以提供服务端渲染,还可以作为中间层连接客户端和后端服务器。客户端的数据请求需要经过中间层代理后,才能向后端服务器请求数据,而服务端渲染(渲染服务器)的请求则不需要代理,可以向后端服务器发送请求,这样可以避免请求路径混乱,有利于更好地排查错误。 2. 引入 thunk 第三个参数构建不同的请求实例,不同请求实例的baseUrl不相同,所以store派发action的时候发送的请求不一样,区分为浏览器请求和服务器请求。
404 状态 和 301 重定向#
- 利用
context的通信功能,在 404 组件中的staticContext的对象上添加属性NOT_FOUND,此时服务端渲染字符串后,获取到传入的context中有这个属性,设置 404 状态码。 - 在组件重定向的时候,组件中
staticContext对象添加属性action: REPLACE, url: xxx,此时服务端渲染字符串后,获取到传入的context中有这些属性,手动重定向页面。
CSS 处理#
- 服务端渲染中使用 isomorphic-style-loader 把 CSS 样式名渲染到 DOM 字符串中,并且提供服务端渲染获取 CSS 样式的方法
_getCss。 - 利用
context的通信功能,把获取到的 CSS 样式注入到渲染字符串的style标签中。
SEO 优化#
使用 react-helmet 定制化组件的title和description属性,优化 SEO。
小结#
这篇文章是以前一个课程React 服务器渲染原理解析与实践的学习笔记,对应的代码已上传到 Github。