我与改革开放同岁 發表於 2020-12-1 09:08:00

图解React SSR中的hydrate

<h2 id="react-csr%E6%B0%B4%E8%BD%A6%E6%A8%A1%E5%9E%8B" class="mume-header">React CSR:水车模型</h2>
<p>当初在理解 React CSR 时做过一个比喻,<strong>把单向数据流比作瀑布模型</strong>:</p>
<blockquote>
<p>瀑布模型:由<code>props</code>(水管)和<code>state</code>(水源)把组件组织起来,组件间数据流向类似于瀑布。数据流向总是从祖先到子孙(从根到叶子),不会逆流</p>
</blockquote>
<p>(摘自深入 React)</p>
<p>单组件的微观视角下,我们把<code>props</code>理解为水管(数据通道),接收外部传递进来的数据(水),每一份<code>state</code>都是一处水源(想象泉眼冒水,即产生数据的地方),将这棵通过<code>props</code>管道连接而成的组件树立起来,就形成了自上而下的水流(瀑布):</p>
<p class="sync-line" data-line="10">&nbsp;</p>
<p><img src="https://thumbs.dreamstime.com/b/dynjandi-waterfall-iceland-one-most-unique-island-155619014.jpg" alt=""></p>
<p class="sync-line" data-line="11">&nbsp;</p>
<p>想象上图整面瀑布墙上有无数的泉眼,<code>state</code>值顺着<code>props</code>管道流淌</p>
<p>从更宏大的视角来看,<strong>组件树就像是一系列竹管连接起来的水车,数据是水源(<code>state</code>、<code>props</code>、<code>context</code>以及外部数据源),水自上而下地流经整个组件树到达叶子组件,渲染出漂亮的视图</strong></p>
<p>先通过一张图来感受竹管输水:</p>
<p class="sync-line" data-line="18">&nbsp;</p>
<p><img src="https://img1.qunarzz.com/travel/d3/1610/a4/e3b27d44cc99e1b5.jpg_r_640x1137x70_a6625f52.jpg" alt=""></p>
<p class="sync-line" data-line="19">&nbsp;</p>
<p>再感受水源以及水车整体的运转:</p>
<p class="sync-line" data-line="22">&nbsp;</p>
<p><img src="http://img3.tbcdn.cn/tfscom/i2/1841360133/TB2UJ64mJ0opuFjSZFxXXaDNVXa_!!1841360133.jpg" alt=""></p>
<p class="sync-line" data-line="23">&nbsp;</p>
<p>左侧的小桶就是外部数据源,<strong>随时舀起一瓢灌到某个组件(竹管)中,让其内部的<code>state</code>(储水)发生变化,变化的水流经过整个子树到达叶子组件,渲染出变化后的视图,这就是交互操作导致数据变化时的组件更新过程</strong></p>
<p class="sync-line" data-line="26">&nbsp;</p>
<h2 id="react-ssr%E4%B8%89%E4%BD%93%E4%BA%BA%E6%A8%A1%E5%9E%8B" class="mume-header">React SSR:三体人模型</h2>
<p>CSR 模式下,我们把水理解为数据,同样适用于 SSR,只是过程稍复杂些:</p>
<ol>
<li>服务端渲染:在服务端注入数据,构建出组件树</li>
<li>序列化成 HTML:脱水成人干</li>
<li>客户端渲染:到达客户端后泡水,激活水流,变回活人</li>
</ol>
<p>类比三体人的生存模式,<strong>乱纪元来临时先脱水成人干(SSR 中的服务端渲染部分),恒纪元到来后再泡水复活(SSR 中的客户端 hydrate 部分)</strong></p>
<p class="sync-line" data-line="36">&nbsp;</p>
<h3 id="%E5%96%9D%E6%B0%B4render" class="mume-header">喝水(render)</h3>
<p>首先要有水可脱,所以先要拉取数据(水),在服务端完成组件首次渲染(mount)的过程:</p>
<p class="sync-line" data-line="40">&nbsp;</p>
<p><img src="http://cdn.ayqy.net/data/home/qxu1001840309/htdocs/cms/wordpress/wp-content/uploads/2020/11/96C4B5DD-20B3-43F9-A8C6-9B220EB2C0A5.png" alt=""></p>
<p class="sync-line" data-line="41">&nbsp;</p>
<p>也就是<strong>根据外部数据构建出初始组件树</strong>,过程中仅执行<code>render</code>及之前的几个生命周期,是为了尽可能缩短保命招数的前摇,尽快脱水</p>
<p class="sync-line" data-line="44">&nbsp;</p>
<h3 id="%E8%84%B1%E6%B0%B4dehydrate" class="mume-header">脱水(dehydrate)</h3>
<p>接着对组件树进行脱水,使其在恶劣的环境同样能够以一种更简单的形态“生存”下来,比如禁用了 JavaScript 的客户端环境</p>
<p>比组件树更简单的形态是 HTML 片段,脱去生命的水气(动态数据),成为风干标本一样的静态快照:</p>
<p class="sync-line" data-line="50">&nbsp;</p>
<p><img src="http://n.sinaimg.cn/sinacn/w449h334/20180108/5d80-fyqincv4241455.jpg" alt=""></p>
<p class="sync-line" data-line="51">&nbsp;</p>
<p>内存里的组件树被序列化成了静态的 HTML 片段,<strong>还能看出来人样(初始视图),不过已经无法与之交互了</strong>,但这种便携的形态尤其适合运输,能够通过网络传输到地球上的某个客户端</p>
<p class="sync-line" data-line="54">&nbsp;</p>
<h3 id="%E6%B3%A8%E6%B0%B4hydrate" class="mume-header">注水(hydrate)</h3>
<p>抵达客户端后,如果环境适宜(没有禁用 JavaScript),就立即开始“浸泡”(hydrate),组件随之复苏</p>
<p><strong>客户端“浸泡”的过程实际上是重新创建了组件树,将新生的水(<code>state</code>、<code>props</code>、<code>context</code>等)注入其中,并将鲜活的组件树塞进服务端渲染的干瘪躯壳里,使之复活</strong>:</p>
<p>&nbsp;</p>
<p class="sync-line" data-line="60"><img src="https://img2020.cnblogs.com/blog/610080/202012/610080-20201201090735986-89300668.jpg" alt="" loading="lazy"></p>
<p class="sync-line" data-line="60">&nbsp;</p>
<p>注水复活其实比三体人浸泡复苏更强大一些,<strong>能够修复肢体性的损伤(缺失的 HTML 结构会重新创建),但并不纠正口歪眼斜之类的小毛病(忽略属性多了少了、属性值对不上之类的问题,具体见React SSR 之原理篇)</strong></p>
<p>P.S.浸泡也需要一定时间,所以在 SSR 模式下,客户端有一段时间是无法正常交互的,注水完成之后才能彻底复活(单向数据流和交互行为都恢复正常)</p>
<p class="sync-line" data-line="66">&nbsp;</p>
<h3 id="%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99" class="mume-header">参考资料</h3>
<ul>
<li>
<p>三体 I:地球往事</p>
</li>
<li>
<p>三体 II:黑暗森林</p>
</li>
</ul>
<p class="sync-line" data-line="72">&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <img src="http://pic.cnitblog.com/face/610080/20140608102954.png" style="vertical-align: top;
float: left;
margin: 7px;
border: 0;"/>
<原创>黯羽轻扬 欢迎转载 不必注明原文出处&lt/原创&gt<br>
<声明>作者水平有限 错误在所难免 欢迎指正&lt/声明&gt<br><br><br>
来源:https://www.cnblogs.com/ayqy/p/ssr-hydrate.html
頁: [1]
查看完整版本: 图解React SSR中的hydrate