遷移一批老文章到掘金css
在微博上看到一篇絕讚的文章html
絕對值得強烈推薦,我想寫這篇文章的緣由就是由於看了這篇文章以爲太棒了!前一陣子我本身確實有比較深刻的拆解分析ReactNative的源碼,一連寫了三篇源碼分析,當Weex開源的那一天,我也第一時間run起了demo,第一時間感覺了這個東西,不少的新奇!不少的驚喜!vue
因爲時間精力所限,我一直沒有深刻的去拆解分析weex,仍是比較初步的瞭解和使用,因此一直沒準備動筆寫一篇對比類的文章,直到我今天看到了這篇文章,基於對RN的理解,看到了做者這麼深入的從方方面面很是多的角度對比分析了兩者,簡直產生了好多共鳴!雖然我不瞭解weex,可是RN的痛點仍是至關至關認同的~哈哈哈哈react
因而才產生了今天的blog。ios
而且在這基礎上,我還想對比一下iOS 與 JSPatch的這套框架,由於不管weex也好rn也好,他們的思路或許一脈相承思路同源,可是和JSPatch這套方案比,那還真是徹底不一樣的兩個世界,這兩個世界差別之大,但又能實現一樣的熱更新功能界面,對比一下真的頗有意思!git
這兩者之間的對比我相信,讀過做者原文的能學到不少,這裏我就不重複囉嗦相同的內容了,不過我仍是想以標註的形式,對於那些對比差別點我仍是想說說個人一些我的的見解^_^github
(後面的內容,豎線+灰色文字是原文,底下是個人見解)web
JS引擎:算法
weex使用V8, ReactNative使用JSCore
這一點和做者交流確認了,iOS上weex依然使用JSCore而在安卓上weex使用了V8。
其實爲何會這樣也是有緣由的,安卓ReactNative雖然使用了JSCore,但這個JSCore不是系統源生的,而是直接打入app包裏的WebKit庫,這也是爲啥安卓項目引入RN包大小會增大4~5M的緣由,ReactNative在iOS上JSCore是系統自帶的,徹底沒法打入app包內,因此iOS的包大小,引入RN後變化並無那麼誇張。
來到了weex,反正安卓RN都是徹底本身植入進去的一整個JSCore,那不如把JSCore換成最新的V8引擎,可是iOS就不一樣了,iOS繼續使用系統自帶的JSCore仍是方便的,系統自帶的不用白不用,別浪費了,否則APP包憑空再多個4~5M,這也是個大槽點哈哈
vue vs react
react模板JSX學習使用有必定的成本 vue更接近經常使用的web開發方式,模板就是普通的html,數據綁定使用mustache風格,樣式直接使用css
我是iOS開發哈,前端領域我不是很瞭解,我是看原文評論裏,不少人說vue用起來更爽,我還沒深刻使用,可是我一個iOS客戶端寫React和JSX仍是有點痛苦的╮(╯_╰)╭,不過值得說的是即使使用了vue,據說weex依然重現了react的virtual dom以及v dom diff算法,做爲渲染性能上的保證,據說哈,我不懂,但願更多的前端大神給我解惑
佈局
二者實現了flexbox的相同子集(都使用了FaceBook的代碼解析),基本沒有區別
哈哈都使用了FaceBook的代碼解析,weex不愧是站在巨人肩膀上的~,順帶FlexBox算法這個仍是好多都在用,聚划算的LuaView在用(lua的flexbox算法),fb的AsyncDisplayKit Layout在用,我其實對這個沒啥好吐槽的,惟一隻有一點
我是一個客戶端開發,對於源生客戶端開發來講,flexbox佈局產生的頁面層級太多了╮(╯_╰)╭,雖然weex和ReactNative,實際上都是純native的界面渲染,但即使是native代碼,View層級多了依然會帶來些許性能問題
而FlexBox的排版就產生了不少這樣的空UIView層級容器.這一層面實際上是能夠優化的,佈局用的View容器其實不用驅動UIManager親自繪製,不知道是否是我把問題想簡單了,你們能夠看一下這圖,一個很簡單的頁面對於native來講,撐死了每一個圖片是一層完事,可是換成了flexbox,層級就變成了這樣
其實我卻是有個解決辦法,就是不之前端的佈局思路去作js腳本驅動native繪製,而是以客戶端的思路,依然用js腳本驅動native繪製
這種思路的老前輩就是早已成熟3~4年的cocos2dx-lua,那種動態腳本更新整個遊戲app,動態更新功能不是個新技術哈~思路早就有。
這種思路其實也是JSPatch的體現,JSPatch雖然寫的是JS代碼,可是全都要以native的編寫代碼風格,native的api使用風格去寫代碼,最終寫出了跟純native如出一轍的功能界面。(相比較cocos2dx whole nativebridge的方案 JSPatch 的runtime bridge方案極度的輕便的多!)
頁面開發
weex提供了一個playground,能夠方便的預覽正在開發的頁面
ReactNative開發一個頁面,須要創建一個native工程,而後編譯運行
這一點也是一個最大的感觸,weex是一套解決三端,安卓,iOS,wap的解決方案,而ReactNative彷彿在facebook創造它的時候,沒有爲他考慮太多的wap,據說攜程在使用RN的時候,先有ReactMix,後有Moles框架,都是在RN之上,在封裝了一層統一wap,iOS,安卓三端的龐大框架,如今好了weex從一開始設計的出發點,就從3端去考慮了
既然支持了wap,wap也是一個環境,天然寫功能頁面的時候,徹底能夠不用Android Studio,不用Xcode,開一個瀏覽器跑起來wap的效果,也就是wap playground,等wap調的差很少了,再搭建native環境去細緻跑
打包
ReactNative官方只能將ReactNative基礎js庫和業務js一塊兒打成一個js bundle,沒有提供分包的功能,須要製做分包打包工具
weex默認打的js bundle只包含業務js代碼,體積小不少,基礎js庫包含在weex sdk中
這個是個大吐槽!RN打出來的包,除了咱們本身寫的index.ios.js之外,把一整個React基礎JS庫全打進包裏了,確實這部分徹底能夠內置app的,否則太浪費動態更新的流量了
擴展性
組件的擴展上,weex和ReactNative具備同樣的能力
三方庫的接入上,weex對網絡,圖片,統計等常見的用戶可能想本身定製的功能,提供了相應的適配接口,能夠由用戶方便的定製,ReactNative須要本身修改源碼
這塊雖然不瞭解weex,但以爲ReactNative作的實在是太讚了,全部RN的native底層,都是一個個的模塊Module,徹底解耦,隨意靈活擴展插拔移除,並且支持開發者自行構建徹底本身的Module,不管是界面仍是數據網絡接口。
我常常說的一句是,ReactNative實際上是一個能夠任意擴展支持的框架,你down下來的源碼,你發現實現不了的功能,擴展一下,妥妥沒問題,你down下來的源碼,你發現性能有問題?很卡?(沒錯我說的就是listview!)我去本身擴展一個啊~iOS基於tableview本身重寫一個帶重用cell的RNTableview~安卓基於recycleview,重寫一個哈?我始終認爲,RN是一個思路,不是一個死的框架
Moudle方法調用線程
weex 能夠經過註解標註是否在UI線程執行
ReactNative在native_modules線程執行
這一點和做者交流了一下,安卓是這樣的,可是iOS不是,iOS裏面,RN每個native_modules線程同樣能夠支持標記控制,只須要重寫module的methodQueue方法,return gcd隊列的mainqueue就行了,RN的module線程控制源碼就是dispatch_async,gcd的queue通常默認用class那麼字符串建立,因此默認是隨機線程惟一隊列,但若是指定async到mainqueue,是能夠直接切換到主線程的
//RCTClipboard類的源碼
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
複製代碼
ListView Android
ReactNative目前採用scrollView使用,有一些性能問題
weex使用recyclerview實現,性能稍好
這個剛纔就提到了的一個大吐槽!RN的ListView!RN的ListView是徹底基於scrollview封裝的,一旦數據夠多,是徹底沒有重用的,業務中若是真的對listview性能痛苦不堪,而且RN提供的一些JS層面的優化性能的屬性還不能知足需求,那是真的得徹底從新本身封裝一個基於native重用的ListView,不少人在使用RN的時候估計也都不能忍ListView而後本身封裝了吧?這下好了,weex幫你作了
2016.7.27補充
ListView缺乏重用機制是一個本質上的問題
無數的人在和我強調ListView沒有問題,我這裏說的是重用機制,重用機制ListView是徹底沒有的,因此ListView在使用上推薦使用分頁的方案,而不是無限制持續上拉加載更多,無上限的持續加載成百上千的Cell,這一點纔是本質層面的問題
ListView因爲這個底層實現的本質,因此在使用上推薦用分頁的方法,不管是20個一屏,仍是30個一頁,實際上沒啥區別,依然是沒法不封頂的增長數量,在一些常規使用方法下ListView有一些基本的優化選項,能夠增長表現力,但這改變不了功能上缺失的本質
這是一個頻繁出現的問題。由於iOS配備了UITableView,經過重用底層的UIViews實現了很是高性能的體驗(相比之下ListView的性能沒有那麼好)。用React Native實現相同效果的工做仍正在進行中,可是在此以前,咱們有一些可用的方法來稍加改進性能以知足咱們的需求。
以上是FaceBook官方的原文翻譯,ListView有沒有問題天然能看到。不用我多說了。。。
順帶Git上已經有UITableView的RN封裝
粗略看了下源碼實現,跟我腦海中的那套方案一致,每個cell內部是一個rootview,能夠經過initParams傳入不一樣數據,進行reload渲染,cell天然進入native OC的重用池,(我太偷懶啦,有了一點思路,一直沒親自實現)
工具鏈
臥槽,我要繼續提一句,weex不虧是站在巨人肩膀上的,開發RN的時候其實有不少痛點,調試界面的時候,我須要全局加框,來查看flexbox佈局是否正確,打包的時候我徹底得本身從新開發分包或者diff包的工具,從而作到增量更新。
當我第一天使用weex的時候,就看到了那個devTools,那個可愛的小button,這可比RN的command + R的能力強大得多,用兩個字評價就是貼心!
我仍是想說
站在巨人的肩膀上看的更遠!
其實在我看來(我不太懂前端,我以爲從React.JS到Vue.JS,前端層面weex和rn的差別應該很是大),在native層面,也就是如何用js寫出來的確是純native界面這個原理上來講,Weex與ReactNative,思路同源,一脈相承,我以爲差別徹底不大,原理是共通的,甚至若是扔掉了JSCore換成C++的luaengine,是否是跟LuaView都原理和核心思想是一致的呢?(luaview也是flexbox用lua寫佈局,最終是native渲染,不過我是真的沒親自跑過luaview的代碼,但我2年前是作cocos2dx-lua的,很是瞭解lua動態更新app的機制)
可是facebook作出來的RN,咱們在使用上確實是有不少的吐槽,這些吐槽徹底不是RN作不到
RN自己是一套很是牛逼很是靈活而模塊擴展式設計,自然支持你任何開發者去補充RN,去擴充RN,這些都不是RN的不足。
若是把ReactNative比做是Linux系統,不懂的人會以爲這也太難用了吧?看視頻軟件須要單獨配置,去yum包去命令行安裝配置一大堆,裝各類軟件都得命令行弄一大堆(好久之前上學的時候純小白對Linux的認知),但不能說Linux系統是不能看視頻解碼小電影的╮(╯_╰)╭
那麼Weex就很人性化的針對痛點,作了更多改善上的事情,更貼心,更易用,更強大,但又不失靈活,開源,擴展都還在(這裏沒有引伸windows缺點的意思)
我甚至能有一種感受,必定是深入的使用過RN,真的瞭解了RN的痛點,才驅動作出這樣一個貼心的項目
這裏我要說一點就是,JSPatch如今不少人是拿他當HotPatch,進行熱修復線上bug去用的,可是他得益於OC極其強大牛逼的運行時,超級靈活的反射機制,不像安卓的hotfix,可能受限於設備,受限於系統,總之反射機制不能徹底發揮做用。
從上面的描述咱們能夠看出來,JSPatch毫不僅僅能夠用來HotFix,而是能夠用來構建全新的功能,而且實現一整個功能模塊的動態更新!
說句實話JSPatch得益於牛逼無敵的OC,runtime,他的靈活能力,是ReactNative&Weex這個方案思路遠遠不能比的。
舉個最簡單的例子,RN與Weex,對於微信支付這種很native的模塊,或許都是採用預先在native代碼裏寫好了實現,最後讓JS去調用(不管是開發者本身擴展的仍是系統擴展的),這個東西就叫jsbridge,但這個bridge很普通,你寫了微信支付的jsbridge,那你的js就有了微信支付的能力,你寫了支付寶支付的jsbridge,那你的js就有了支付寶的能力,你寫了iOS平臺的IAP的jsbridge,那你的js就有了IAP的能力,若是你沒寫咋辦?你的JS就辦不到,要知道,擴寫這些jsbridge,都是須要發版的,都是不能動態更新的。
換句話說,若是一開始使用RN的app只開發了支付寶的支付功能,寫好了支付寶的jsbridge,因而發版上線了,等某一天忽然想接入蘋果的applepay,那麼只有一個辦法,那就是從新發版,從新寫好了applepay的jsbridge,再次提交蘋果審覈(我舉了個系統庫的例子,但意義能夠擴展一下)
可是對於JSPatch來講,JSPatch也是一套基於JSCore的bridge,可是牛逼就牛逼在JSPatch不是這種常規的normal jsbridge,而是runtime jsbridge,runtime的特色就是實現沒有被任何oc代碼預先寫好的功能,同時還能修改已經被OC代碼預先寫好的功能!
若是整個APP都是RNorWeex包一個殼子,全部功能都是js寫的,那麼若是不須要更新jsbridge,那麼確實能夠實現,修改任何功能模塊,寫新的功能模塊,均可以用RNorWeex進行熱更新,徹底不發版。
可是我相信,至關多的APP都是部分界面保留原有工程的native,部分界面,部分新界面採用RNorWeex(那些已經成熟的大app必定是這樣的,不可能推翻重寫)
那麼問題來了,RN能更新用RN寫的界面,RN能更新那些本來native的界面嗎?答案是不行,JSPatch能夠。RN能夠開發一整個新功能界面,動態更新到app上,可是這個新功能界面怎麼打開呢?辦法有一個,app內有一套URLRoute的路由機制,而且輔助以雲端可控的路由配置表,那麼確實能夠改變某些位置本來的界面跳轉,從而跳轉打開全新的RN界面,實現了新RN界面的動態更新,可是JSPatch就不須要URLRoute這套全局跳轉的輔助機制幫忙,JSPatch徹底有能力更改任何已經由OC寫好的代碼,隨意的改變跳轉到新界面,隨意的增長新按鈕,不改變舊界面就把新界面打開!
與JSPatch能力和機制相似的還有阿里的Wax
Wax本是好久之前國外的大神編寫的一套用Lua寫OC的動態框架,可是這個框架太老了,老到尚未支持蘋果64位就沒人維護了,年代過久遠了
大衆點評的大神在Wax的基礎上融入了運行時,變成了WaxPatch,但這年代也好久遠,也是在沒有支持64位的時候就不維護了。
直到去年10月,阿里宣佈接管維護了Wax,而且大量擴展了海量功能,由於之前的wax也好waxpatch也好,支持的動態runtime能力還特別少。
不過都是純iOS平臺,畢竟這種思路和玩法徹底依託於無敵的OC Runtime
和JSPatch的做者@bang哥學習以及交流了不少動態更新方面的見解,bang哥最近也在醞釀一篇大做,專程去對比JSPatch與ReactNative的對比。
bang哥的見解
對比 | 學習成本 | 接入成本 | 熱更新能力 | 開發效率 | 性能體驗 |
---|---|---|---|---|---|
Weex&RN | 高 | 高 | 中 | 高,跨平臺 | 高 |
JSPatch | 低 | 低 | 強 | 中,不跨平臺 | 高 |
總的來講,JSPatch在學習成本,接入成本,熱更新能力上佔優,而 React Native 在開發效率和跨平臺能力上佔優,你們能夠根據需求的不一樣選用不一樣的熱更新方案。JSPatch 目前仍在不斷髮展中,歡迎參與這個開源項目的開發。
原文還沒發佈,等到發佈了我必定第一時間補上原文連接。
這實際上是對native開發人員來講的,JSPatch全部的API,全部的寫法,全部界面的佈局,都是純native開發人員最熟悉的,只是須要略微熟悉下從OC變JS的轉變(最基礎的js語法)(甚至有一些不是太智能的oc直接轉js的工具),以及JSPatch的一些獨特規定,對於native iOS開發人員來講(就是我啦),學習css+html式的佈局,理解flexbox(忍受flexbox那層級的吐槽),其實遠沒有直接按着native的思惟方式寫JSPatch方便。
ReactNative&Weex的方案更貼近web開發人員,尤爲是熟練掌握React和Vue的,可是當面臨自定義擴展native能力也就是bridge開發的時候,其實仍是須要native代碼能力,而且視你的擴展需求不一樣,可能須要比較深的native能力。
因此從我一個native開發人員的角度來說,JSPatch學習成本低不少
你能想象 JSPatch的核心代碼,不算邊角擴展,全部源碼只有2個文件嗎?jspatch.js
和JPEngine.h.m
這接入成本可想而知啊,下源碼,扔進工程,完事啊~哈哈哈哈哈
前面解釋的夠多了,在iOS平臺上,JSPatch其runtime能力,真的是不管weex仍是ReactNative都是遠遠沒法比擬的
確實Weex & ReactNative的輔助開發工具超級多,而且HTML+CSS式的界面佈局,熟練了之後開發真的是太快了╮(╯_╰)╭
JSPatch仍是native的開發方式,輔助工具也開發了不少,你們能夠細看JSPatch的Github和bang哥的Github和博客,但效率上我以爲仍是比不上的╮(╯_╰)╭
JSPatch目前在使用上會和webview有必定的衝突,若是有須要動態用jspatch寫一個含有webview的頁面的時候,會有略微的麻煩,和不穩定因素,在GitWiki上有明確介紹瞭如何在JSPatch裏面使用webview,好比初始化的時候先於JSPatch構建一個Webview而後在銷燬啊,好比js建立webview記得須要十分當心的使用一個performInOc的api啊,不要按着經常使用方法使用,還有就是不穩定,個人case是某一些特殊的業務場景下,會偶現crash(很低機率,可是頻繁操做能夠復現)
JSPatch在OC與JS交互的時候,是支持直接把一個OC對象,一個界面,一個model,直接傳給JS上下文裏面的,這個OC對象會所以引用計數+1,而且隨着JS上下問的垃圾回收機制,對這個OC對象進行引用計數的額外控制,在JS上下文內是沒法去查看這個OC對象的,可是卻能夠指定任何OC對象本來的方法,而後發送回OC環境去操做這個OC對象。
RN在OC與JS交互的時候,是徹底不支持傳遞任何OC對象的,全部能在JS與OC中間傳遞的,必定是能夠被json化,字符化的內容,數字,字典,數組,字符串,因此RN專門有個RCTConvert類去專門處理,json的序列化model化,反序列化反model化。那麼RN是如何經過JS去控制一個純OC的界面View呢?是經過viewTag,JS控制的每個界面效果,都是傳過來一個tag,讓native建立,讓native修改,native會儲存住這些tag到一個hashmap裏,這樣JS纔可以不直接傳遞OC對象,而是傳遞一個數字,從而控制OC對象
兩者的實現差別,是會形成一些底層運行差別的,OC與JS對象只傳遞JSON其實就保證了,JS上下文的內存與OC上下文的內存徹底沒有互通,各自的內從各自控制,JS是一套垃圾回收機制,而OC是一套引用計數機制。
JSPatch將兩者進行了互通,這些互通的對象內存管理則是一套,又有引用計數控制,又有JS的垃圾回收,當JS的垃圾回收,而且iOS的引用計數歸0,纔會銷燬。
這裏沒有優劣之分,JSPatch在雙內存控制機制下,也是能夠正常work沒有問題的,RN&Weex的這套機制,內存上簡單清晰,不過這都是底層實現的問題,上層使用,都是沒問題的
相關係列文章