亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

pekonchan / 823人閱讀

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

而在體積上,則通過刪除一些對線上沒用的代碼實現(xiàn)迷你化效果。

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

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

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

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

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

resolve: {
   alias: {
      "react": "anujs",
      "react-dom": "anujs",
        // 若要兼容 IE 請使用以下配置
        // "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"
        //如果你在移動端用到了onTouchTap事件
        "react-tap-event-plugin": "anujs/lib/injectTapEventPlugin",  
   }
},

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

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

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/91928.html

相關(guān)文章

  • 2017-09-19 前端日報

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

    Leo_chen 評論0 收藏0
  • 前端資源分享-只為更好前端

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

    zxhaaa 評論0 收藏0
  • 前端資源分享-只為更好前端

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

    JouyPub 評論0 收藏0
  • 前端資源分享-只為更好前端

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

    vslam 評論0 收藏0

發(fā)表評論

0條評論

pekonchan

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<