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