react中出現的"hydrate"這個單詞到底是什麼意思?

react的一些源碼解讀和討論中(包括一些react-like的庫),經常會出現「hydrate」這個詞,通過直接翻譯我沒辦法get到其中的意思...然後多看了一些資料,自己的一些理解比較捉急,就不放上來了.... 所以希望經驗人士能解釋一下...

比如 React 16 SSR - hydration on client not working if server html !== client html · Issue #10591 · facebook/react 這個討論中 rgrove commented 25 days ago 的回答就總是提到這個詞....


是這樣的:

1)React 的事件綁定,在服務端渲染時,並不會以 & 這種內聯事件形態出現。所以,ReactDOMServer 渲染的內容在「結構-樣式-行為」鐵三角關係里,缺失了「行為」

2)在 React v15 版本里,ReactDOM.render 方法可以根據 data-react-checksum 的標記,復用 ReactDOMServer 的渲染結果,不重複渲染,而是根據 data-reactid 屬性,找到需要綁定的事件元素,進行事件綁定的處理。補完「結構-樣式-行為」。

3)在 React v16 版本里,ReactDOMServer 渲染的內容不再有 data-react 的屬性,而是儘可能復用 SSR 的 HTML 結構。

這就帶來了一個問題,ReactDOM.render 不再能夠簡單地用 data-react-checksum 的存在性來判斷是否應該嘗試復用,如果每次 ReactDOM.render 都要儘可能嘗試復用,性能和語義都會出現問題。所以, ReactDOM 提供了一個新的 API, ReactDOM.hydrate() 。

4)在 React v17 版本里,ReactDOM.render 則直接不再具有復用 SSR 內容的功能。見:https://github.com/facebook/react/blob/master/src/renderers/dom/shared/__tests__/ReactRenderDocument-test.js#L32-L34

結論:hydrate 描述的是 ReactDOM 復用 ReactDOMServer 服務端渲染的內容時儘可能保留結構,並補充事件綁定等 Client 特有內容的過程。


在火車上,簡單答一下這個詞在react中是ssr相關的,因為ssr時伺服器輸出的是字元串,而瀏覽器端需要根據這些字元串完成react的初始化工作,比如創建組件實例,這樣才能響應用戶操作。這個過程就叫hydrate,有時候也會說re-hydrate

可以把hydrate理解成給乾癟的字元串」注水」


談一談 Angular 中的 (De)hydration 部分。事實上 Angular 在很多非 SSR 的部分都()存在著 Hydration 的概念,這是由於 Angular 的(某一個)早期設計中的實現機制所決定的。(下文中「早期的 Angular」均指代這一特定時期

早期的 Angular 採用了 DOM 復用的實現方式,即對於每個組件(或組件中的獨立模版),先根據其模版構造出相應的 DOM Node(s),對應於 ProtoViewRef,之後等到該組件需要實例化的時候,把對應的 DOM Node(s) 對象 clone 一遍,然後在 clone 出來的 DOM Node(s) 中處理組件實例的具體內容。因此,這裡就會涉及到一個「由靜態 DOM Node(s) 到動態可工作 DOM Node(s)」的轉變過程,可以叫做 Hydration。

當然,Angular 團隊的腦洞並不只是這麼簡單。

在 NG-Conf 2015 中,Angular 團隊祭出了一份 Angular v2(早期測試)版本與 Angular(JS) v1.3 版本的性能比較圖:

從這裡開始傳出了 Angular v2 比 Angular(JS) v1 快 5 倍的說法(「快 5 倍」這個說法從語言角度是有問題的,希望不要在任何正式文章中像這樣誤用),但準確地說,圖中列出的是使用 View Cache 的 v2 版本比 v1.3 版本快 5 倍。於是問題來了,到底什麼是 View Cache 呢?

簡單地說,就是某些視圖不再需要出現在頁面中的時候,並不真正把它銷毀,而是把實例相關的內容剝離,然後緩存 DOM 本身,等下次需要的時候無需 clone 直接使用。於是,這裡又出現了「把已經和實例綁定可工作的 DOM Node(s) 重新簡化到純結構狀態」這個過程,叫做 Dehydration。

由於 View Cache 機制的存在,Hydration 和 Dehydration 過程便是 Angular 中的家常便飯,並不需要 SSR 的參與。(有些類似於 Virtual List 中的重用機制,不過並不是簡單的固定形式和固定數量

然而,在之後的早期實現中(是的,仍然還是早期實現,離大部分人聽說 Angular 都還差很久),不論是 DOM clone 的機制還是 View Cache 的機制都去掉了(實踐證明 DOM clone 並不會比重新創建更快,View Cache 由於內存管理過於複雜不實用),所以在正式版本的 Angular 中幾乎不需要使用這些概念,不過文檔中仍然有些殘留,例如 ChangeDetectionStrategy:

不過在最新的文檔中已經被移除。

簡單的解釋就是,這裡直接使用了 DOM Node(s) 作為 Browser 中模版的實際存在形式(和 HTML Template Tag 的工作方式類似),而視圖的存在形式也是 DOM Node(s),因此 Hydration 和 Dehydration 發生在模版與視圖的轉換過程當中,用於 DOM 與應用其它部分的結合/解除結合。

在 SSR 中,當然就不再是從模版到視圖了,而是從初始的靜態視圖到可交互的動態視圖,也不存在 Dehydration 這個解除的過程。


謝邀。

hydrate就是「注水」,一個完整的網頁可以看成是乾貨摻了水的結果,純數據只是乾巴巴的乾貨,不是給人看的,但是「注水」之後,變成可以展示的HTML,就變成瀏覽器可以解釋用戶能看的東西了,這過程就是hydrate。

還有兩個詞,dehydrate和rehydrate,dehydrate是「脫水」,一般指的是伺服器端渲染的時候,準備純數據的過程,這些數據隨HTML一起發給瀏覽器,因為React需要用這些數據重新渲染一遍(v16之前是這樣),在瀏覽器端,根據這些數據重新渲染一遍的過程,就叫做rehydrate。

看過《三體》嗎?三體星人長期進化出一種能力,缺水的時候脫水,變成乾巴巴人干,由其他人拎著走就行,到了有水的地方,潑上水,又原地滿血復活了,React的伺服器端渲染也是一樣的道理。感謝劉慈欣的這本小說,我在《深入淺出React和Redux》里引用了這個梗。


就是把字元串變成可用組件渲染到瀏覽器。


在preact代碼中,hydrate (hydrating) 是一個表示 "native dom對象是否沒被preact渲染過" 的flag。首次渲染時hydrating為true, 第二次及以後是false。

簡單看了一下,猜測在react中也是類似的意思。

preact代碼中具體是這樣的:

Preact和React不同,在渲染時是直接比較vdom和native dom的。但為了加快速度,實際會在native dom的node上存一個JS對象,用於緩存上次渲染此node時的props。第二次以後渲染時就先比較vdom和props cache,只在不同時才更新node。

如果把native dom想成是一種物質,把preact添加在其間的 props cache 等屬性當成水,那麼首次渲染時將preact的屬性附在native dom這個行為就叫hydrate,即"摻水"。

相關代碼在preact內的src/vdom/diff.js 可以找到。

廣告: 我在寫一個介紹preact內部代碼的系列文章,有興趣的可以先關注我知乎專欄或blog。


在vue源碼中也出現了 @尤雨溪


推薦閱讀:

如何看待 BrendanEich、Vjeux 等人就 React Native 的討論?
這些手機銷售前端頁面用了哪些技術?
JS 中 var add=function(){} add(a)(b)(c); 是什麼簡寫?
匿名函數的this指向為什麼是window?

TAG:Web開發 | 前端開發 | 前端開發框架和庫 | React |