這波React屬實被針對了
大家好,我卡頌。
昨天在網(wǎng)上愉快沖浪時,看到一篇框架測評,效果屬實爆炸。
作者用React和Solid.js開發(fā)了同樣的Demo。為什么用Solid.js和React對比呢,讓我們看看Solid.js的API:
- Hooks
- Context、Portal API
- Error Boundaries
不能說和React多雷同,只能說一摸一樣吧。而且Solid.js也用JSX描述視圖,所以一個React應(yīng)用要改為Solid.js應(yīng)用的成本很小。
具體測評結(jié)果怎么樣呢,差了快3倍,這一波React屬實被針對了。
本文參考SolidJS vs React: I've Built the Same App On Both Libraries.[1]
為啥差這么多簡單介紹下這個Demo,初始渲染空白列表:
首次mount完成后發(fā)起請求,渲染列表數(shù)據(jù):
Rick和Morty真愛粉無疑了
這是兩個應(yīng)用Chrome Dev Tools Performance面板的結(jié)果:
左React 右Solid.js
解釋下其中幾個關(guān)鍵指標(biāo):
- Loading:發(fā)起網(wǎng)絡(luò)請求、解析HTML的時間
- Scripting:解析、編譯、執(zhí)行JS的時間(包括垃圾回收時間)
- Rendering:style和layout計算
- Painting:paint、composite、解碼圖片
具體關(guān)注Scripting,左475ms(React),右176ms(Solid.js)
2倍多的差距,這么夸張?
問題出在哪
前端框架的工作流程可以簡單用三個步驟總結(jié):
- 觸發(fā)交互
- 計算交互會影響哪些DOM
- 執(zhí)行DOM操作
這里的交互可能是首屏渲染,可能是點擊造成的狀態(tài)變化、可能是請求數(shù)據(jù)......
在React中,步驟2是在運行時完成的,而在Solid.js中是在編譯時完成的。
具體來說,該步驟在React中被稱為reconcile,更普遍的稱呼是虛擬DOM的diff算法。
在Performance面板下面的Call Tree中可以看到,執(zhí)行XHR Load(請求列表數(shù)據(jù))前有個很耗時的操作(Function Call),該操作即reconcile。
而在Solid.js應(yīng)用中就沒有這個耗時的操作:
在編譯時,Solid.js會將JSX直接編譯為狀態(tài)與操作DOM的方法之間的聯(lián)系。
由于JSX太過靈活,為了在編譯時有更多線索建立這種聯(lián)系,Solid.js在React原有JSX組件基礎(chǔ)上提供了一些控制流組件:
舉個例子,下面是遍歷列表項在兩個框架中的實現(xiàn)區(qū)別:
- // React
- <ul>
- {list.map(
- item => <li>{item.name}</li>
- )}
- </ul>
- <ul>
- // Solid.js
- <ul>
- <For each={list}>
- {(item) => <li>{item.name}</li>}
- </For>
- </ul>
For組件替代了JS中的數(shù)組map方法。
當(dāng)Solid.js在編譯時完成這些工作,在運行時每次更新實際只用完成步驟1和3,省去了大部分步驟2的時間。
雖然React對reconcile有優(yōu)化策略,但隨著應(yīng)用體積增大,或者項目成員不完全遵守最佳實踐,勢必會造成在步驟2上花費的時間越來越多。
Solid.js提前建立狀態(tài)與操作DOM的方法之間的聯(lián)系,雖然需要在運行時占用更多內(nèi)存保存這種對應(yīng)關(guān)系,但是卻省去了大部分步驟2的時間,是一種典型的空間換時間的策略。
總結(jié)
說了這么多,雖然看起來Solid.js對比React在框架的某些方面是有優(yōu)勢的,但并不能撼動React的統(tǒng)治地位。
畢竟,React這么流行和他快不快一點關(guān)系都沒有,社區(qū)生態(tài)繁榮才是最重要的。
還有個有意思的事,這里是文中的2個Demo地址:
- Solid.js版[2]
- React版[3]
Demo中獲取數(shù)據(jù)的API的域名是rickandmortyapi.com,居然還有這種網(wǎng)站......
參考資料
[1]SolidJS vs React: I've Built the Same App On Both Libraries.:
https://dev.to/ogzhanolguncu/solidjs-vs-react-i-ve-built-the-same-app-on-both-libraries-4cfa[2]Solid.js版:
https://github.com/ogzhanolguncu/rick-and-morty-solidjs[3]React版:
https://github.com/ogzhanolguncu/react-rick