下一代 React Native 會是什麼樣的?— Recos

咱們團隊很早就接入了 React Native,其動態化下發面對咱們這個三天兩頭改界面的團隊是挺契合的。雖然 Flutter 大火,但咱們如今並無去嘗試,一個是動態化對於咱們過重要了, 另一個是咱們跨平臺選擇了「業務邏輯使用KMM, 音視頻用 C++,界面用RN」的路子,能夠知足團隊的需求,還有一個緣由是,如今即便是跨平臺技術了,業務太多,客戶端的人也太少了,已經被困在業務裏走不動了,心有點累。前端

可是 RN 被詬病的主要仍是性能太差,一堆不知緣由的 Native Crash。咱們不能由於它存在問題,那就換另外一套技術,而是要去優化它,解決它的問題,這也是咱們技術走向深度的一個路子。git

隨着時代的發展,Native UI 已經有了新的產物, Android 這邊誕生了 Compose, iOS 誕生了 SwiftUI, 都是採用聲明式的語法,能夠說 React 開創了 UI 的新時代, Native 已經有新的產物,那麼 React Native 是否也應該與時俱進?不過 React Native 官方團隊的開發節奏有點慢啊,一年前提出了 JSI 去解決通訊問題,而後就一直卡在 TurboModule 裏走不出來了。 因此去年我就有一個想法,我只去用 React, 從新用 Compose 實現一個 React Native,徹底採用 JSI 與 TurboModule 的形式, 由於沒有歷史包袱,也只去支持 Hermes 引擎,並且只去支持咱們用到組件,理論上會簡單不少, 業餘時間,我也的確去這麼作了,也初步作出了 Demo, 事件流程、基礎組件、Flex 佈局等都實現出來,看似有點搞頭,可是在長列表上,個人想法是 js 渲染出全部的 virtual dom, 而後到了 Compose 端, 將它們做爲數據傳遞給 LazyColumn 進行渲染, 可實現發現,js 去建立成千上萬個 virtual dom 時依舊很耗時, 這個路子走不通,想了一些其它的路子,可是須要去魔改下 React,不想這麼作,最終好像又要回到 React Native 社區提供的 RecyclerListView 的形式, 有點不爽。github

不過想着想着,又有了新的思路, React 是聲明式的語法, SwiftUICompose 也是生命式的語法,那麼咱們可不能夠把它從 React 的寫法翻譯到 ComposeSwiftUI 上呢。 基於靜態代碼翻譯,確定可行, 可是咱們想要的是動態下發,那該怎麼搞呢?在與同事的討論中,我想到了一個方案: 一個語言,在編譯前端的呈現是什麼呢? 是 AST 結構,那麼咱們是否是能夠序列化這個 AST,而後在 Compse 環境去解釋執行這個 AST 呢? 那咱們就來試一下。babel

JS 的 AST 須要咱們本身去解析文件生成嗎? 不,前端有強大的 babel,因此咱們能輕鬆拿到 js 的 ast 結構, 咱們能夠適當的簡化下,渠道多餘的信息,減少生成文件的大小, 由於流程就變成這樣子了:markdown

design.jpeg

想法有了,那就去作作看,新建個項目, 命名爲: Recos閉包

Github 地址:github.com/cgspine/Rec…app

目前 Compose 的 Demo 已經寫出來了,開篇就是一個長列表, 能夠無任何依賴的執行下面代碼:框架

function Item1(item, onItemClick){
    const onClick = useCallback(() => {
        onItemClick(item)
    })

    return <Text style={{ color:'#fff' }} onClick={ onClick }>偶數:{item.name}, {item.count}</Text>

}

function Item2(item, onItemClick){
    const onClick = useCallback(() => {
        onItemClick(item)
    })

    return <Text style={{ color:'#fff' }} onClick={ onClick }>奇數:{item.name}, {item.count}</Text>
}

function HelloWorld(current){

    const [data, setData] = useState([])

    useEffect(() => {
        let ret = []
        for(let i = 0; i < 1000; i++){
            ret.push({
                name: 'item' + i,
                index: i,
                count: 0
            })
        }
        setData(ret)
    }, [current])

    let render = function (i) {
        let item = data[i]
        if(item.index % 2 == 0){
            return Item1(item, (it) => {
                it.count = it.count + 1
                setData(data)
            })
        }else{
            return Item2(item, (it) => {
                it.count = it.count + 2
                setData(data)
            })
        }
    }

    return <RecyclerView count = { data.length } render = { render }>Hello World!</RecyclerView>
}
複製代碼

React 裏的 useState, useCallback, useEffect 我都去實現了下,感受努努力,就能夠用到生產環境了。dom

若是去實現下 React Native 的全部接口, 那就能夠與之相兼容了。ide

目前看來,這個就徹底兩個方面的能力:

  1. 編譯原理的前端知識,咱們要去寫 js 解析器了, 如今我寫的這些代碼,只是能工做,效率什麼都須要逐步優化,還有不少語法解析沒支持到。
  2. 考察 js 的基本功,什麼做用域、閉包、變量提高,對象、原型鏈, 都須要從根本去搞懂它。

一些想法的產生、落地都須要不少基本功的落地,而不是隻會調用某些框架就能搞定的,繼續努力吧, 有興趣的而且承認這個思路的同窗,能夠參與到這個項目來,努努力,讓咱們再次重鑄JS昔日輝煌,幹掉 ReactNative,幹掉 Flutter。

相關文章
相關標籤/搜索