首页 > 其他分享 >React前后端如何同构,防止重复渲染

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

时间:2023-11-08 09:22:20浏览次数:38  
标签:react 同构 浏览器 render dom 渲染 React 组件

什么叫前后端同构?

为了解决某些问题(比如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 值写在根元素的属性上:
React前后端如何同构,防止重复渲染React前后端如何同构,防止重复渲染

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

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

如果 checksum 比对不一致,在 开发环境 和 测试环境 会在浏览器console中输出以下警告内容:
React前后端如何同构,防止重复渲染React前后端如何同构,防止重复渲染

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

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

标签:react,同构,浏览器,render,dom,渲染,React,组件
From: https://www.cnblogs.com/roccn/p/17816573.html

相关文章

  • vue-test -----ListDemo 列表渲染
    <template><h3>数组</h3><button@click="addnums">添加数据</button><pv-for="(item,index)innums":key="index">{{item}}</p></template><script>exportdefault{name:......
  • 单个Nginx发布多个react静态页面
    在有些网络环境中,端口是一种比较稀缺的资源,而我们又恰好有多个前端项目需要发布,我们可以采取将多个项目映射到同一个端口上面的方案加以解决。本教程前端项目主要以react为主,部署在linux服务器上。1.将项目资源的访问地址修改为相对方式在react项目package.json中,添加或者修改......
  • #yyds干货盘点#React-初始化渲染
    1.环境准备初始化项目:npxcreate-react-appsimple-react删除一些代码,最关键的内容就是:src/index.jspublic/index.htmlpackage.json中的dependencies和scripts:2.JSX介绍JSX是JavaScript的一种语法扩展。JSX到普通Javascript的代码的转化是通过babel完成的。3.React.createElement编......
  • iOS渲染卡死应该如何解决
    1)iOS渲染卡死应该如何解决2)C#传给C++的Byte数组如何释放3)EAssetBundle.Unload(true)触发长时间卡顿的原因这是第358篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习。UWA社区主页:community.uwa4d.comUWAQQ群:46......
  • React中状态提升
    代码案例functionA({onGetAName}){constname=`>${newDate().getTime()}<`;return(<div>ThisisAcomponent!{/*箭头函数形式来调用事件函数*/}<buttononClick={()=>onGetAName(name)}>sendAN......
  • React学习笔记18-非受控组件
    1.非受控组件的定义非受控组件即状态不是完全由React的state来控制的组件React要编写一个非受控组件,可以使用ref来从DOM节点中获取表单数据,就是非受控组件。importReact,{Component}from'react'exportdefaultclassAppextendsComponent{myusername=R......
  • React学习笔记19-受控组件
    1.受控组件的定义React组件的数据渲染是否被调用者传递的props完全控制,完全控制则为受控组件,否则非受控组件。即React的state成为组件的唯一数据源。 下面用一个小案例来演示,案例中todolist组件的唯一数据源就是State,todolist组件就是一个受控组件importReact,{Com......
  • #yyds干货盘点#Expo 搭建 React-native 项目
    Expo搭建RN项目Expo 搭建项目有两种方式:一种是通过Expo的脚手架 expo-cli;一种是通过 create-react-native-app。本文采用第一种。1、安装expo-clinpminstallexpo-cli--global2、创建项目expoinitmy-new-project会有两类模板让你选择:托管工作流,裸露工作流(感觉叫原生工......
  • 专访虚拟人科技:如何利用 3DCAT 实时云渲染打造元宇宙空间
    自古以来,人们对理想世界的探索从未停止,而最近元宇宙的热潮加速了这一步伐,带来了许多新的应用。作为元宇宙的关键入口,虚拟现实(VR)将成为连接虚拟和现实的桥梁。苹果发布的VISIONPRO头戴设备将人们对VR的关注推向了一个新的高度。在这个充满无限可能性的元宇宙中,杭州虚拟人科技有......
  • 从FrameDebugger看Unity渲染
     Unity如何渲染一个3D+2D的游戏画面,今天通过FrameDebugger来看下Unity内置渲染管线的渲染策略, 后续再出一些URP渲染管线相关的文章。    Unity渲染场景的几个主要部分    Unity内置渲染管线是基于摄像机来进行渲染的,每个摄像机按照摄像机的渲染顺序来依次渲染,渲......