React CSR:水車模型
當初在理解 React CSR 時做過一個比喻,把單向數據流比作瀑布模型:
瀑布模型:由props(水管)和state(水源)把組件組織起來,組件間數據流向類似於瀑布。數據流向總是從祖先到子孫(從根到葉子),不會逆流
(摘自深入 React)
單組件的微觀視角下,我們把props理解為水管(數據通道),接收外部傳遞進來的數據(水),每一份state都是一處水源(想象泉眼冒水,即產生數據的地方),將這棵通過props管道連接而成的組件樹立起來,就形成了自上而下的水流(瀑布):
想象上圖整面瀑布牆上有無數的泉眼,state值順着props管道流淌
從更宏大的視角來看,組件樹就像是一系列竹管連接起來的水車,數據是水源(state、props、context以及外部數據源),水自上而下地流經整個組件樹到達葉子組件,渲染出漂亮的視圖
先通過一張圖來感受竹管輸水:
再感受水源以及水車整體的運轉:
左側的小桶就是外部數據源,隨時舀起一瓢灌到某個組件(竹管)中,讓其內部的state(儲水)發生變化,變化的水流經過整個子樹到達葉子組件,渲染出變化後的視圖,這就是交互操作導致數據變化時的組件更新過程
React SSR:三體人模型
CSR 模式下,我們把水理解為數據,同樣適用於 SSR,只是過程稍複雜些:
- 服務端渲染:在服務端注入數據,構建出組件樹
- 序列化成 HTML:脱水成人幹
- 客户端渲染:到達客户端後泡水,激活水流,變回活人
類比三體人的生存模式,亂紀元來臨時先脱水成人幹(SSR 中的服務端渲染部分),恆紀元到來後再泡水復活(SSR 中的客户端 hydrate 部分)
喝水(render)
首先要有水可脱,所以先要拉取數據(水),在服務端完成組件首次渲染(mount)的過程:
也就是根據外部數據構建出初始組件樹,過程中僅執行render及之前的幾個生命週期,是為了儘可能縮短保命招數的前搖,儘快脱水
脱水(dehydrate)
接着對組件樹進行脱水,使其在惡劣的環境同樣能夠以一種更簡單的形態“生存”下來,比如禁用了 JavaScript 的客户端環境
比組件樹更簡單的形態是 HTML 片段,脱去生命的水氣(動態數據),成為風乾標本一樣的靜態快照:
內存裏的組件樹被序列化成了靜態的 HTML 片段,還能看出來人樣(初始視圖),不過已經無法與之交互了,但這種便攜的形態尤其適合運輸,能夠通過網絡傳輸到地球上的某個客户端
注水(hydrate)
抵達客户端後,如果環境適宜(沒有禁用 JavaScript),就立即開始“浸泡”(hydrate),組件隨之復甦
客户端“浸泡”的過程實際上是重新創建了組件樹,將新生的水(state、props、context等)注入其中,並將鮮活的組件樹塞進服務端渲染的乾癟軀殼裏,使之復活:
注水復活其實比三體人浸泡復甦更強大一些,能夠修復肢體性的損傷(缺失的 HTML 結構會重新創建),但並不糾正口歪眼斜之類的小毛病(忽略屬性多了少了、屬性值對不上之類的問題,具體見React SSR 之原理篇)
P.S.浸泡也需要一定時間,所以在 SSR 模式下,客户端有一段時間是無法正常交互的,注水完成之後才能徹底復活(單向數據流和交互行為都恢復正常)
參考資料
- 三體 I:地球往事
- 三體 II:黑暗森林
有所得、有所惑,真好
關注「前端向後」微信公眾號,你將收穫一系列「用心原創」的高質量技術文章,主題包括但不限於前端、Node.js以及服務端技術
本文首發於 ayqy.net ,原文鏈接:http://www.ayqy.net/blog/ssr-...