成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

去哪兒網(wǎng)迷你React的研發(fā)心得

pekonchan / 782人閱讀

摘要:市面上竟然擁有多個(gè)虛擬庫(kù)。虛擬庫(kù),就是出來(lái)后的一種新式庫(kù),以虛擬與算法為核心,屏蔽操作,操作數(shù)據(jù)即操作視圖。及其他虛擬庫(kù)已經(jīng)將虛擬的生成交由與處理了,因此不同點(diǎn)是,虛擬的結(jié)構(gòu)與算法。因此虛擬庫(kù)是分為兩大派系算法派與擬態(tài)派。

去哪兒網(wǎng)迷你React是年初立項(xiàng)的新作品,在這前,去哪兒網(wǎng)已經(jīng)深耕多年,擁有QRN(react-native的公司制定版),HY(基于React的hybird方案), yo(基于React的移動(dòng)UI庫(kù)),QRN-web(基于React的三端合一移植方案),此外,像機(jī)票等部門(mén)也大規(guī)模將React用于前臺(tái)頁(yè)面,后臺(tái)頁(yè)面就更不在話下。

如此廣泛地應(yīng)用React,我們熟曉其優(yōu)缺點(diǎn)。優(yōu)點(diǎn)是代碼的可維護(hù)性大大提高,性能卓然!但缺點(diǎn)也明顯,由于體積太大,React.js+React-DOM.js超過(guò)3萬(wàn)行,體量過(guò)3MB,已經(jīng)加上immutable.js , redux, redux-react, react-router等全家桶,工程師一行代碼沒(méi)有寫(xiě),已經(jīng)好幾MB了。這在過(guò)去絕對(duì)不可想象,要知道,體積意味著流量,流量代表著金錢(qián),越大越燒錢(qián),越大下載速度越慢,用戶體驗(yàn)越差,用戶就會(huì)流失?,F(xiàn)在問(wèn)題擺在我們面前,我們就得解決。雖然webpack官網(wǎng)有各種瘦身方案,但瘦死的大象也比馬大。這是一個(gè)如此普遍存在的問(wèn)題,因此外國(guó)人肯定也遇到過(guò),思考過(guò),提出什么新點(diǎn)子——所有這一切,都指向一個(gè)名詞,“迷你React”。

作為一個(gè)生態(tài)圈成熟的標(biāo)志,一個(gè)庫(kù)出名了,就各種偏門(mén)補(bǔ)丁,閃光效果往上加,庫(kù)難免會(huì)膨脹,不爽的人就會(huì)推出迷你化方案。上一個(gè)世代是jQuery與zepto。React的迷你方案也有不少,preact, inferno, react-lite, dio, rax……

但問(wèn)題不是簡(jiǎn)單到直接從github找一個(gè)迷你React庫(kù)替換上就能搞定。之所以稱為迷你,肯定有所欠缺,如果是內(nèi)部實(shí)現(xiàn)的改良也罷,如果閹割了功能可不是鬧著玩。恰恰他們就好這口,因此現(xiàn)有方案不能滿足我們。我們需要一個(gè)能直接替換,或至少95%的業(yè)務(wù)代碼不用動(dòng)。這意味著這迷你框架,需要與React的接口完全一致,并且全面支持它的全家桶。當(dāng)然細(xì)化一下來(lái)的需來(lái)就更多了,早期說(shuō)只要支持移動(dòng),因此取名為react-mobile,后來(lái)連iE8也要支持,因此這活不能指望別人,我們自己動(dòng)手?jǐn)]了。

我們先來(lái)一趟競(jìng)品分析。為了加快產(chǎn)出速度,能借鑒的盡可能借鑒。React推出以后,針對(duì)其性能研究衍生出不少庫(kù),針對(duì)其體積也誕生出大量仿品。它比jQuery更加繽紛多采。市面上竟然擁有100多個(gè)虛擬DOM庫(kù)。虛擬DOM庫(kù),就是React出來(lái)后的一種新式庫(kù),以虛擬DOM與diff算法為核心,屏蔽DOM操作,操作數(shù)據(jù)即操作視圖。這聽(tīng)起來(lái)有點(diǎn)像MVVM,MVVM也是屏蔽DOM操作,操作數(shù)據(jù)即操作視圖,但它是以VM為核心。

React及其他虛擬DOM庫(kù)已經(jīng)將虛擬DOM的生成交由JSX與babel處理了,因此不同點(diǎn)是,虛擬DOM的結(jié)構(gòu)與diff算法。虛擬DOM萬(wàn)宗不離其變是三大屬性,type, props, children,當(dāng)然也可以改一下別名,babel可以做相應(yīng)配置。此外,虛擬DOM可以加入更多冗余標(biāo)識(shí),以幫diff算法的改良。

React最初推出時(shí)也不火,那時(shí)的招牌與現(xiàn)在性能不什么兩樣,也是高性能。但是JSX離經(jīng)背道,與業(yè)界宣揚(yáng)了多年的前后端分離,數(shù)據(jù)結(jié)構(gòu)樣式分離等教條差太遠(yuǎn)了,一直默默在角落里畫(huà)圈。直到RN出來(lái),解決原生編寫(xiě)界面的痛苦才一炮而紅。大家才留意它的性能,它的性能背后的diff算法。最早研究React的diff算法是virtual-dom這個(gè)庫(kù),是基于經(jīng)典的DFS算法。后來(lái)相應(yīng)的算法就多起來(lái)。最后才是從接口進(jìn)行模擬,就是所謂的React-like框架。因此虛擬DOM庫(kù)是分為兩大派系:算法派與擬態(tài)派。

下面將從這兩大派系進(jìn)行扼要的描述。

將前端回歸到算法上的探索是前端框架史上的一個(gè)巨大進(jìn)步。之前是MVVM將數(shù)據(jù)從繁復(fù)的DOM操作分離出來(lái)。正因?yàn)橛辛思償?shù)據(jù),并且數(shù)據(jù)結(jié)構(gòu)可控,那么算法才有發(fā)揮的余地。

最開(kāi)始出現(xiàn)的是 virtual-dom這個(gè)庫(kù),是大家好奇React為什么這么快而搞鼓出來(lái)的。它的實(shí)現(xiàn)是非常學(xué)院風(fēng)格,通過(guò)深度優(yōu)先搜索與in-order tree來(lái)實(shí)現(xiàn)高效的diff。它與React后來(lái)公開(kāi)出來(lái)的算法是很不一樣。

然后是cito.js的橫空出世,它對(duì)今后所有虛擬DOM的算法都有重大影響。它采用兩端同時(shí)進(jìn)行比較的算法,將diff速度拉高到幾個(gè)層次。

緊隨其后的是kivi.js,在cito.js的基出提出兩項(xiàng)優(yōu)化方案,使用key實(shí)現(xiàn)移動(dòng)追蹤及基于key的編輯長(zhǎng)度矩離算法應(yīng)用(算法復(fù)雜度 為O(n^2))。

但這樣的diff算法太過(guò)復(fù)雜了,于是后來(lái)者snabbdom將kivi.js進(jìn)行簡(jiǎn)化,去掉編輯長(zhǎng)度矩離算法,調(diào)整兩端比較算法。速度略有損失,但可讀性大大提高。再之后,就是著名的vue2.0 把sanbbdom整個(gè)庫(kù)整合掉了。

當(dāng)然算法派的老大是inferno,它使用多種優(yōu)化方案將性能提至最高,因此其作者便邀請(qǐng)進(jìn)react core team,負(fù)責(zé)react的性能優(yōu)化了。這個(gè)我后面會(huì)詳細(xì)。

再看擬態(tài)派。React的接口并不多,但是其組件的實(shí)現(xiàn)是相當(dāng)有難度。它的生命周期是如何運(yùn)作,需要對(duì)源碼有深刻的理解,因此它們出來(lái)得比較晚。我們的學(xué)習(xí)對(duì)象也就是它們幾個(gè)。

先說(shuō)虛擬DOM。虛擬DOM就是一個(gè)普通的JS對(duì)象,通常擁有三個(gè)屬性,type, props, children。但無(wú)狀態(tài)組件出來(lái)后,children改放到props中。此外,有些元素還有ref屬性,可以是字符串與函數(shù)。在數(shù)組里,為了提高diff速度,又多出了key屬性。bable會(huì)將JSX這些屬性轉(zhuǎn)換為一個(gè)VNode對(duì)象。這是虛擬DOM的最小單元。所有虛擬DOM會(huì)組成一棵樹(shù),叫虛擬DOM樹(shù)。

為了防止每次都是整個(gè)樹(shù)進(jìn)行diff,需要形成子樹(shù)的概念,于是出現(xiàn)組件了。組件有render方法,會(huì)返回一個(gè)虛擬DOM,這個(gè)虛擬DOM及其子孫,就形成一棵子樹(shù)。但render方法不是虛擬DOM的東西,于是我們規(guī)定當(dāng)虛擬DOM為一個(gè)函數(shù)時(shí),如果這個(gè)函數(shù)繼承于React.Component,這個(gè)方法的實(shí)例必須有render方法。于是我們就像虛擬DOM與組件統(tǒng)合起來(lái)了?;蛘哐苌@兩個(gè)稱呼,原子虛擬DOM與組件虛擬DOM。原子虛擬DOM對(duì)應(yīng)元素節(jié)點(diǎn),而組件則是用來(lái)產(chǎn)出原子虛擬DOM。此外,原子虛擬DOM還能包含一些東西,字符串與數(shù)字與null。字符串與數(shù)字對(duì)應(yīng)文本節(jié)點(diǎn),null對(duì)應(yīng)注釋節(jié)點(diǎn)。

一個(gè)組件虛擬DOM實(shí)例化為組件后,會(huì)返回原子虛擬DOM或另一個(gè)組件虛擬DOM。這就形成函數(shù)式編程上的高階函數(shù)的機(jī)制,因此進(jìn)行出無(wú)狀態(tài)函數(shù)組件,就是虛擬DOM的type屬性就是一個(gè)函數(shù),不繼承其他東西了。

組件虛擬DOM的實(shí)例化過(guò)程是非常復(fù)雜,如果能簡(jiǎn)化這過(guò)程,簡(jiǎn)化其結(jié)構(gòu),這性能就上去了。

此外組件的實(shí)例本身就巨耗性能,因此官方推薦頁(yè)面的結(jié)構(gòu)如下,通過(guò)最少量的有狀態(tài)組件(smart component)控制無(wú)狀態(tài)組件(dumb component)的變化,所有狀態(tài)通過(guò)redux在路由進(jìn)行分發(fā)。

經(jīng)過(guò)一番比較后,我們著手開(kāi)發(fā)自己的迷你React。這個(gè)過(guò)程也比較坎坷,這還是有前人參照物的情況下,可想而知,當(dāng)初facebook開(kāi)發(fā)出React這樣一個(gè)獨(dú)行特立的框架時(shí),是多么艱辛。我們?cè)谶@半年總共搞了三個(gè)東西,第一還孵化失敗。

最初是基于react-lite,考慮時(shí)當(dāng)時(shí)是我們母公司的人搞的,方便交流。但后來(lái)發(fā)現(xiàn)它的事件系統(tǒng)太雞肋,難以擴(kuò)展,最后放棄了。

第二代是基于preact,代號(hào)qreact, 國(guó)內(nèi)也有許多公司基于它做自己的迷你化方案,因?yàn)楣俜教峁┝艘粋€(gè)preact-compat的模塊。但是preact-compat是使用Object.defineProperty來(lái)實(shí)現(xiàn)一些屬性名映射與同步的,因此不支持IE8,并且使用了Object.defineProperty會(huì)嚴(yán)重拖慢速度。preact本身也有不少BUG,最著名的有三個(gè),生命周期的unmount鉤子不能保證在mount之前執(zhí)行,元素節(jié)點(diǎn)的重復(fù)利用沒(méi)有清理樣式會(huì)導(dǎo)致出錯(cuò),同一組孩子下可能存在同名的key導(dǎo)致排序失敗。這些我們都為官方提issue,并且在我們的版本中進(jìn)行修復(fù)了。第二代也公司內(nèi)部幾個(gè)項(xiàng)目中試水落地,反映不錯(cuò)。

第三代是我們團(tuán)隊(duì)獨(dú)力開(kāi)發(fā),a內(nèi)部代號(hào)anu,正式名稱仍然是 QReact,不過(guò)演進(jìn)到了 QReact 1.0 了 (現(xiàn)在的版本使用了 1.0 大版本,因?yàn)橹斑@個(gè)版本沒(méi)被占用,所以沒(méi)跳到 2.0)。在對(duì)preact縫縫補(bǔ)補(bǔ)的過(guò)程,掌握不少核心知識(shí),新的框架是使用全新的算法,全新的結(jié)構(gòu)。由于不使用高級(jí)API,理論上能支持到IE6,但我們公司只需支持到IE8。

Qreact1.0使用requestAnimationFrame來(lái)穩(wěn)定它的運(yùn)行幀數(shù),保證在60幀每秒的流暢速度。由于bable會(huì)對(duì)type進(jìn)行打補(bǔ)丁,內(nèi)部統(tǒng)一用typeNumber代替type進(jìn)行類型判定。使用列隊(duì)保證生命周期鉤子按順序執(zhí)行。使用__rerender標(biāo)識(shí)一個(gè)組件在一次大的更新只會(huì)被render一次。凡此種種,經(jīng)過(guò)大量測(cè)試,它們的接口與React別無(wú)二致,甚至React廢棄的接口createClass, PropTypes,我們都有相應(yīng)的polyfill。

下面是Qreact1.0的測(cè)試數(shù)據(jù)。
從性能上,直追preact。

從體積上,是官方react的1/4至1/5之間。

這里透露一下React性能爆表的秘密,除了diff算法外,setState的合并操作也是一個(gè)關(guān)鍵。當(dāng)組件沒(méi)有插入到DOM樹(shù)前,用戶在componentWillMount方法多次執(zhí)行setState,這些state是不會(huì)觸發(fā)更新,而是存放到一個(gè)數(shù)組中,然后在render方法里進(jìn)行合并與應(yīng)用。當(dāng)一個(gè)組件進(jìn)行更新,可能是用戶在componentDidMount或者事件回調(diào)執(zhí)行setState,這時(shí)更新是即時(shí)的,同步的,但這之次再setState,它就不會(huì)更新了,它的state會(huì)進(jìn)入列隊(duì)。此外,如果用戶在componentWillReceiveProps多次執(zhí)行setState,也會(huì)產(chǎn)生延遲。React這種行為是保證頁(yè)面的更新次數(shù)最少,同時(shí)用戶不會(huì)察覺(jué)它沒(méi)有更新。它只是將state進(jìn)行了合并。Qreact1.0是完全遵循了這些規(guī)則,從而實(shí)現(xiàn)了高性能。

而在體積上,則通過(guò)刪除一些對(duì)線上沒(méi)用的代碼實(shí)現(xiàn)迷你化效果。

但僅是這樣不足以大吹特吹了。為了超越React的性能,從inferno與preact借簽了不少手段。

最值得一提的是hydrate機(jī)制,通過(guò)合并相鄰字符串,從而減少文本節(jié)點(diǎn)的生成,從而減少diff次數(shù)。

最后還有一個(gè)壓軸大戲,不做測(cè)試不知道,原來(lái)高級(jí)API是如何耗性能。通過(guò)去掉Object.freeze, Object.defineProperty這些es5方法, 框架就有10幀的提升!

說(shuō)了這么多,來(lái)些實(shí)際可運(yùn)行的例子吧。目前,Qreact跑通內(nèi)部幾套測(cè)試,已經(jīng)在金融與大搜的項(xiàng)目使用。它的第二版也在機(jī)票一個(gè)擁有820個(gè)模塊的大項(xiàng)目中試水,在IE8下良好運(yùn)行。

如果大家想在項(xiàng)目中使用qreact,可以在webpack或ykit的config中如下配置:

resolve: {
   alias: {
      "react": "anujs",
      "react-dom": "anujs",
        // 若要兼容 IE 請(qǐng)使用以下配置
        // "react": "anujs/dist/ReactIE",
        // "react-dom": "anujs/dist/ReactIE",
    
        // 如果引用了 prop-types 或 create-react-class
        // 需要添加如下別名
        "prop-types": "anujs/lib/ReactPropTypes",
        "create-react-class": "anujs/lib/createClass"
        //如果你在移動(dòng)端用到了onTouchTap事件
        "react-tap-event-plugin": "anujs/lib/injectTapEventPlugin",  
   }
},

如果大家對(duì)qreact在感興趣,歡迎與我聯(lián)系,也歡迎大家為我的框架加星。

https://github.com/RubyLouvre/anu/
https://github.com/YMFE/qreact

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91928.html

相關(guān)文章

  • 2017-09-19 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選與實(shí)現(xiàn)讓你的網(wǎng)站秒配證書(shū)借助實(shí)現(xiàn)元素滾動(dòng)自動(dòng)環(huán)繞的劉海大型架構(gòu)設(shè)計(jì)騰訊大會(huì)圖文筆記中文翻譯種高效縮寫(xiě)法個(gè)人文章個(gè)節(jié)省開(kāi)發(fā)者時(shí)間的實(shí)用工具庫(kù)與資源簡(jiǎn)書(shū)通用類和結(jié)構(gòu)與樣式分離眾成翻譯性能調(diào)優(yōu)之調(diào)試篇一知乎專欄進(jìn)階系列 2017-09-19 前端日?qǐng)?bào) 精選 VirtualDOM與diff(Vue實(shí)現(xiàn))讓你的網(wǎng)站秒配 HTTPS 證書(shū)借助CSS Shapes實(shí)現(xiàn)元素滾動(dòng)自動(dòng)環(huán)繞iP...

    Leo_chen 評(píng)論0 收藏0
  • 前端資源分享-只為更好前端

    摘要:一團(tuán)隊(duì)組織網(wǎng)站說(shuō)明騰訊團(tuán)隊(duì)騰訊前端團(tuán)隊(duì),代表作品,致力于前端技術(shù)的研究騰訊社交用戶體驗(yàn)設(shè)計(jì),簡(jiǎn)稱,騰訊設(shè)計(jì)團(tuán)隊(duì)網(wǎng)站騰訊用戶研究與體驗(yàn)設(shè)計(jì)部百度前端研發(fā)部出品淘寶前端團(tuán)隊(duì)用技術(shù)為體驗(yàn)提供無(wú)限可能凹凸實(shí)驗(yàn)室京東用戶體驗(yàn)設(shè)計(jì)部出品奇舞團(tuán)奇虎旗下前 一、團(tuán)隊(duì)組織 網(wǎng)站 說(shuō)明 騰訊 AlloyTeam 團(tuán)隊(duì) 騰訊Web前端團(tuán)隊(duì),代表作品WebQQ,致力于前端技術(shù)的研究 ISUX 騰...

    zxhaaa 評(píng)論0 收藏0
  • 前端資源分享-只為更好前端

    摘要:一團(tuán)隊(duì)組織網(wǎng)站說(shuō)明騰訊團(tuán)隊(duì)騰訊前端團(tuán)隊(duì),代表作品,致力于前端技術(shù)的研究騰訊社交用戶體驗(yàn)設(shè)計(jì),簡(jiǎn)稱,騰訊設(shè)計(jì)團(tuán)隊(duì)網(wǎng)站騰訊用戶研究與體驗(yàn)設(shè)計(jì)部百度前端研發(fā)部出品淘寶前端團(tuán)隊(duì)用技術(shù)為體驗(yàn)提供無(wú)限可能凹凸實(shí)驗(yàn)室京東用戶體驗(yàn)設(shè)計(jì)部出品奇舞團(tuán)奇虎旗下前 一、團(tuán)隊(duì)組織 網(wǎng)站 說(shuō)明 騰訊 AlloyTeam 團(tuán)隊(duì) 騰訊Web前端團(tuán)隊(duì),代表作品WebQQ,致力于前端技術(shù)的研究 ISUX 騰...

    JouyPub 評(píng)論0 收藏0
  • 前端資源分享-只為更好前端

    摘要:一團(tuán)隊(duì)組織網(wǎng)站說(shuō)明騰訊團(tuán)隊(duì)騰訊前端團(tuán)隊(duì),代表作品,致力于前端技術(shù)的研究騰訊社交用戶體驗(yàn)設(shè)計(jì),簡(jiǎn)稱,騰訊設(shè)計(jì)團(tuán)隊(duì)網(wǎng)站騰訊用戶研究與體驗(yàn)設(shè)計(jì)部百度前端研發(fā)部出品淘寶前端團(tuán)隊(duì)用技術(shù)為體驗(yàn)提供無(wú)限可能凹凸實(shí)驗(yàn)室京東用戶體驗(yàn)設(shè)計(jì)部出品奇舞團(tuán)奇虎旗下前 一、團(tuán)隊(duì)組織 網(wǎng)站 說(shuō)明 騰訊 AlloyTeam 團(tuán)隊(duì) 騰訊Web前端團(tuán)隊(duì),代表作品WebQQ,致力于前端技術(shù)的研究 ISUX 騰...

    vslam 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

pekonchan

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<