文档章节

React前后端同构防止重复渲染

随风溜达的向日葵
 随风溜达的向日葵
发布于 2017/08/25 11:58
字数 1196
阅读 1874
收藏 43
点赞 2
评论 2

什么叫前后端同构?

为了解决某些问题(比如SEO、提升渲染速度等)react 提供了2个方法在服务端生成一个HTML文本格式的字符串。在得到了这个HTML格式的字符串之后,通常会将其组装成一个页面直接返回给用户的浏览器。

到这里,服务端的活已经干完了,然后就是浏览器这边干活。

浏览器拿到HTML文本后,立刻进行渲染将内容呈现给用户。然后加载页面所需的 .js 文件,然后执行 JavaScript 脚本,然后开始初始化 react 组件…………

到这里问题就来了。react 初始化组件后会执行组件内所有 render () 方法,然后生成虚拟DOM的树形结构,然后在适当的时候将虚拟dom到浏览器的真实dom中。因为 react 总是根据虚拟dom来生成真实dom,所以最后会把服务器端渲染好的HTML全部替换掉。

上面这个事情说不是问题确实也不是问题,无非就是用户看到页面然后“闪现”一下。说是问题还真是个问题,产品会拿着这毛病从用户体验的角度在各种场合和你死磕半个月。磕累了你索性把服务端渲染关了,然后运营又拿着SEO的问题准备和你开始撕逼了。

聪明如 Facebook 的工程师当然想到了这些问题,所以他们在ReactDOMServer.renderToString(element) 方法中提供了一个 checksum 机制。

关于 checksum 官网 并没有太多介绍,但是国内外的各路博客介绍了不少。我一直想找 react 开发者关于这个机制的介绍一直没找到……。

前后端同构就是保证前端和后端的dom结构一致,不会发生重复渲染。react 使用 checksum 机制进行保障。

什么叫React首屏渲染?

简单的说就是 react 在浏览器内存中第一次生成的虚拟 dom 树。切记是虚拟 dom ,而不是浏览器的dom

了解 react 的应该知道,所有 react 组件都有一个 render() 方法(如果使用function方式编写的组件会把function里的所有代码都塞到 render() 方法中去)。当ReactDOM.render( element, container, [callback] )方法执行时,会执行以下步骤:

  1. 所有组件的会先进行初始化(es6执行构造函数)。
  2. 所有组件的 render () 方法会被调用一次,完成这个过程后会得到一颗虚拟的 dom 树。
  3.  react 会将虚拟dom转换成浏览器dom,完成后调用组件的 componentDidMount() 方法告诉你已经装载到浏览器上了。

在上面这个过程成中,步骤2完成后即为完成 react 的首屏渲染。结合 checksum 机制步骤3有可能不会执行。

当组件状态发生变更时( setState() 生命周期函数被调用)或者 父组件渲染时(父组件的 render() 方法被调用),当前组件的 render() 方法都会被执行,都有可能会导致虚拟dom变更,但是这些变更和首屏渲染没任何关系了。

React前后端同构首屏渲染

了解了同构和首屏渲染,就好理解如何解决首屏不重复渲染的问题了。

首先服务端渲染完之后会有一个 checksum 值写在根元素的属性上:

这个 checksum 是根据服务端生成的HTML内容哈希计算得到的。

然后在浏览器加载完所有的js文件之后,开始执行前面介绍的 ReactDOM.render( element, container, [callback] )  初始化渲染的三个步骤。当执行完第二步生成虚拟dom后,react 会根虚拟dom用相同的算法计算一个哈希值,如果和 checksum 一致则认为服务器已经完成渲染,不会再执行第三步。

如果 checksum 比对不一致,在 开发环境 和 测试环境 会在浏览器console中输出以下警告内容:

生产环境不会输出任何警告。

同构渲染的内容就这么多,原理其实蛮简单的,无非就是保证DOM一致。但是结合代码分片、异步加载、服务端调接口异步组装数据等等功能后,如何保证服务端和浏览器端第一次渲染的dom一致还得花不少功夫。不过原理清楚了,事情总能办成。

© 著作权归作者所有

共有 人打赏支持
随风溜达的向日葵
粉丝 205
博文 64
码字总数 140871
作品 0
广州
其他
加载中

评论(2)

随风溜达的向日葵
随风溜达的向日葵

引用来自“i5--lou”的评论

说了半天你还是没有介绍这个checksum咋用啊
这里说的只是原理。怎么用看这里:https://my.oschina.net/chkui/blog/1525488。略长。
i5--lou
i5--lou
说了半天你还是没有介绍这个checksum咋用啊
以同构之名,再谈 Redux/Vuex 的必要性

最近在菲麦社群中,有关 Redux/Vuex 是否真的需要的讨论异常激烈,我认为,在前端工程化的道路上, Redux/Vuex 非常有必要,在此前的文章中,我提到过:可以将 Vuex 认为是 Vue 的高级事件总...

小虫巨蟹
2017/12/18
0
0
服务端渲染 vs 客户端渲染

概念 服务端渲染(吐) 服务端在返回 html 之前,在特定的区域,符号里用数据填充,再给客户端,客户端只负责解析 HTML 。 服务端渲染 也被称为 fat-server, thin-client 模式 服务端渲染 客...

三毛丶
2017/11/19
0
0
基于koa+fis3+swig前后端isomorphic同构实现

  (认真把这篇文章看完,保证你会学到很多,如果没学到请联系作者或直接报警)   随着前端技术的不断变革,前端从后台吐页面 -> 前端MVC -> mvvm、react -> node直出 ->同构跨端的大致发...

ouven
2016/04/21
417
0
IMVC(同构 MVC)的前端实践

导语 随着 Backbone 等老牌框架的逐渐衰退,前端 MVC 发展缓慢,有逐渐被 MVVM/Flux 所取代的趋势。 然而,纵观近几年的发展,可以发现一点,React/Vue 和 Redux/Vuex 是分别在 MVC 中的 Vi...

工业聚
2017/11/22
0
0
珍惜生命远离旭哥哥/node-template

#node-template nodeJs项目,JavaScript同构模板项目。 使用express + react + redux + react-router ,实现服务器渲染+动态路由控制。主要目的是实现react的单页面应用,但不局限于单页面。...

珍惜生命远离旭哥哥
2016/11/20
0
0
FEDAY2016之旅

前戏 2016/3/21 补上参会的完整记录,这个问题从一开始我就是准备“自问自答”的,希望可以通过这种形式把大会的干货分享给更多人。 出发/到达 我跟同事周周是周六凌晨1点才到的广州,住的地...

某小A
2017/11/29
0
0
挨踢部落直播课堂第七期:如何使用React构建同构(isomorphic)应用

随着前端的发展,为了用户体验,H5越来越多的使用SPA架构,导致JS代码越来越多,体积也变的庞大,这时传统的ajax方式在首屏访问时就变得慢了,而且ajax在seo方面有天然的弱势,这时服务端渲染...

51CTO编辑部
2017/11/30
0
0
Webpack实战-构建同构应用

同构应用是指写一份代码但可同时在浏览器和服务器中运行的应用。 认识同构应用 现在大多数单页应用的视图都是通过 JavaScript 代码在浏览器端渲染出来的,但在浏览器端渲染的坏处有: 搜索引...

2017/12/19
0
0
webkixi/FKP-REST

About This is a starter boilerplate app I've put together using the following technologies: Both client and server make calls to load data from separate API server KOA React Mon......

webkixi
2016/08/11
0
0
面向亿万级用户的QQ一般做什么?——兴趣部落的 Web 同构直出分享

欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:李强,腾讯web开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。 原文链接:http://wetest.qq.com/la...

腾讯云社区
2017/11/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JVM学习手册(一):查看堆内存使用情况以及排错

平时出现内存溢出以及死锁,一般处理方式都是查看日志,找到抛出异常的代码行,然后本地分析代码,但是这样对于线上排查十分糟糕,这段时间在研究JVM发现了几个比较好的工具和指令. 1.针对频繁GC和...

勤奋的蚂蚁
2分钟前
0
0
Java IO类库之ObjectInputStream和ObjectOutPutStream

一、ObjectOutputStream 1 - ObjectOuputStream介绍 ObjectOutputStream(对象字节输出流),用于将一个序列化对象写入到创建ObjectOutputStream时传入的底层字节输入流中,通过源码可知该类继...

老韭菜
14分钟前
0
0
17.TCP:传输控制协议

介绍 TCP和UDP使用同一网络层(IP),但TCP提供了面向连接、可靠的传输层服务 TCP传输给IP层的信息单位称为报文段或段 TCP通过如下方式保证可靠性: 应用数据被分割成TCP认为最合适发送的数据...

loda0128
24分钟前
0
0
重装Oracle时出现environment variable "PATH"错误的解决办法

在win7 64位下重新安装oracle 11g,一直报environment variable "PATH"的错误,按说明将path里多余的路径删除,但没办法解决。选择忽略错误继续安装,装一半会报CRC错误,还是安装失败。最好...

良言
29分钟前
0
0
TensorFlow 全连接的mnist

全连接的mnist import tensorflow as tf# 导入 MINST 数据集from tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("MNIST_data/", one_ho......

阿豪boy
29分钟前
0
0
JAVA 三种WebService 规范

JAVA 中共有三种WebService 规范,分别是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。 1. Jaxws(掌握) JAX-WS 的全称为 Java API for XML-Based Webservices ,早期的基于SOAP 的JAVA 的Web 服务...

onedotdot
48分钟前
0
0
将博客搬至CSDN

将博客搬至CSDN

xpbob
49分钟前
1
0
Aidl进程间通信详细介绍

目录介绍 1.问题答疑 2.Aidl相关属性介绍 2.1 AIDL所支持的数据类型 2.2 服务端和客户端 2.3 AIDL的基本概念 3.实际开发中案例操作 3.1 aidl通信业务需求 3.2 操作步骤伪代码 3.3 服务端操作...

潇湘剑雨
今天
0
0
python爬虫日志(3)下载图片

import urlliburl='https://xxx.jpg'#图片地址res=urllib.request.urlopen(url)#此函数用于对url的访问data=res.read() #字节流with open(r'D:\1.jpg',"wb") as code: c...

茫羽行
今天
0
0
vue中$emit的用法

1、父组件可以使用 props 把数据传给子组件。 2、子组件可以使用 $emit 触发父组件的自定义事件。 vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运...

JamesView
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部