尤雨溪爲什麼要推出 Vapor Mode?
Vapor Mode
是尤雨溪在 2022 Year In Review 給定相中提出的概念,本篇文章我們將直觀感受下尤雨溪爲啥要推出Vapor Mode
。
💎前情提要
-
🚀 React 編譯之後是
Jsx
函數返回的虛擬DOM
-
🚀 Vue 編譯之後是
render
函數返回的虛擬DOM
-
🚀 SolidJS 編譯之後返回的
真實DOM
字符串 -
🚀 Svelte 編譯之後返回的是
真實DOM
片段
React
由於架構機制決定了每當狀態發生改變,從當前組件開始一直到葉子組件重新加載。
Vue
由於給每個組件建立了watchEffect
監聽機制,每當組件依賴的狀態發生改變,當前組件重新加載。
SolidJS
和Svelte
由於在編譯之後就確定了當狀態發生改變UI
隨之變化的關係,所以僅僅是具體DOM
的重新加載。
根據這些不同的更新粗細粒度,他們被分爲
💎直觀感受
爲了直觀感受更新時的區別,現在我們設計如下關係的組件:
GrandFather
|
Father
|
Child
每個組件的背景色都是隨機的,並且在Father
組件中,實現了一個Count
功能。
我們用四個框架分別實現。下面只給出一個例子。
生成隨機顏色:
`#${(~~(Math.random()*(1<<24))).toString(16)}`
Father
組件如下:
// Father.jsx
import React, { useState } from 'react'
const Father = () => {
const [count, setCount] = useState(0)
const onClick = () => setCount(count => count ++)
return (
<div style={{ display: "flex" }}>
<div
onClick={() => onClick()}
style={{
height: 100,
width: `40vw`,
background: `#${(~~(Math.random() * (1 << 24))).toString(16)}`,
}}
>
{count}
<Child />
</div>
<div
onClick={() => onClick()}
style={{
height: 100,
width: `40vw`,
background: `#${(~~(Math.random() * (1 << 24))).toString(16)}`,
}}
></div>
</div>
)
}
export default Father
接下來,我們看看他們在觸發onClick
時的不同表現吧。
🚀 React
🚀 Vue
🚀 Svelte
🚀 SolidJS
🚀 結論
上面的圖中,可以直觀的看到:
React
在當前組件狀態發生變化時,從當前組件開始,包括子組件都被重新加載了。
Vue
僅僅是當前組件重新加載。
SolidJS
、Svelte
僅僅是重新加載組件!
💎總結
在項目比較小時,SolidJS
、Svelte
的優勢不會很明顯,
但是當面對大型項目時,React
和Vue
的性能短板就顯露出來了。
面對這樣的壓力,尤雨溪在年初的展望裏已經預告了Vapor mode
,該模式的靈感就是受到了SolidJS
的啓發。
它可以在給定相同的Vue SFC
前提下,與當前基於虛擬DOM
的輸出相比,Vapor Mode
將其編譯成性能更高、使用更少內存且需要更少運行時支持代碼的JavaScript
輸出。
對於React
由於架構機制的限制,目前很難做出根本性的改變,
對於開發者,我們可以選擇手動優化。例如,將組件使用memo
包裹起來。
const Child = memo(() => <Comp>your comp</Comp>)
此時上面的例子中,React
的效果更新效果就和Vue
類似了。
我們爲了演示每次dom
都是重新加載的,所以樣式是直接這樣寫的。
background: `#${(~~(Math.random() * (1 << 24))).toString(16)}`
在實際開發中,要儘量避免無意義的重複計算,尤其React
中,比如:
// bad
<Comp
style={
margin: window.screen.width / 3 * 2
}
/>
// good
const App = () => {
const margin = useMemo(() => window.screen.width / 3 * 2, [])
return <Comp style={ margin } />
}
// bettter
const margin = window.screen.width / 3 * 2
const App = () => {
return <Comp style={ margin } />
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/QrBOF6pJ1GxVAnbPmYn0xA