希望從開發難度,生態及前景等方面進行考慮


每次回答這種問題都會引發「黨爭」,其實有些吃力不討好,不過既然是「蹭」熱度,那我就不從誰更優秀去評判,成年人不談對錯只聊利弊,就容我從另一個角度「瞎扯」。

我之前閑著蛋疼做過一個分析,大概分析了 53 框大廠的應用,其中明面上:

  • 帶有 flutter 的有 20 款;
  • 帶有 react-native 的有 22 款;
  • 帶有 weex 的有 17 款;

國內大廠在移動端跨平台的框架接入分析 - 掘金?

juejin.im

怎麼樣,這個數據有沒有給你帶來不一樣的感覺?其實做技術的很容易就陷入到「孕婦效應」里,做 rn 的認為 flutter 很小眾火不起來,做 flutter 的認為 rn 要涼,畢竟大家圈子就那麼大,而事實上現在 rn 和 flutter 在不同需求的市場上依舊過的滋潤。

另外這裡為什麼說明面上呢,因為有一些 App 是使用動態化去下發動態庫的,所以明面上看不出來。

就連 weex 都會有像 uni-app 的市場存在,另外現在阿里、位元組跳動和小米都已經開始在把 flutter pc 在推進到生產中使用,所以在我們「看不見」的角落都有它們各自的市場,只是我們選擇了我們想看到的。

另外有時候企業會需要用新技術來維護前沿的技術形象,而員工需要新技術來創造 kpi 考核。

說到底語言誰更牛逼,框架誰更先進的爭執不過是「技術人」自己的攀比,要生存要賺錢還是得有業務,所以實際上選擇哪門框架的理由更多是:業務需要、面試需要、市場需要。從我的角度推薦:

  • 如果你的業務更看重熱更新,你的方向和技術棧更貼近 React ,你的崗位更多是前端領域,那麼你選擇 react-native 會更適合,投入產出比更高。
  • 如果你是原生開發,你更看重性能和跨平台的兼容,那麼 flutter 會更適合你,因為現在 flutter 的開發崗位更多和原生開發綁定在一起。

新框架的出現每次都會有人歡喜有人愁,說到底排斥的理由很大程度是因為未知和不理解。

我曾經舉過一個有趣的例子,如下圖所示是不同階段扳手,可以看到:

  • 從 1 到 2 用戶擰螺母需要準備的扳手數量減少了;
  • 從 2 到 3 扳手變得更加帥氣有力,並且附帶的「攻擊力」也有所上升;

那問題來了:

一、既然有 2 這樣便捷的扳手,那 1 這種扳手還有必要存在嗎?

  • 答案是有的,因為 1 中的扳手性價比更高,在特點的場景下會更輕便。

二、那扳手 2 既然都滿足大部分場景了,扳手 3 有必要存在嗎?

  • 答案也是有的,因為 3 中的扳手更加「帥氣「,同時從健壯的角度更可靠。

扯這兩個問題其實是想表達:每個框架都有自己的市場,而你會選擇哪種框架,主要還是前面所說的業務和工作類型決定。

當然這裡還有一個有趣的誤解:

扳手 2 升級後看起來比扳手 1 牛逼了,所以作為使用扳手 2 的我比使用扳手 1 的牛逼?

開發的鄙視鏈很多時候就是這麼來的,但是從我的角度出發:牛逼的是扳手的製造者,而作為使用者,我們都是踩著別人的肩膀混口飯吃,在乎的不過是踩著誰更舒服而已。

當我批判一個框架時,我會想想我自己能不能造出比它更好的輪子?

最後,用好扳手的能力比選擇扳手更重要,不管是 flutter 或者 react-native ,有的人也許只是寫了 hello world 或者跑了個開源項目就開始跟風批判,很多時候框架的性能並不是我們的瓶頸,而使用的姿勢和理解的程度才是我們的短板。

真實經歷過有用 iOS 模擬器 debug 和我說 flutter 性能問題,而 debug 的 JIT 和 release 的 AOT 區別不用多說,官方都曾表示過 flutter 在 iOS 模擬器上不能使用 GPU ,所以用性能測試的場景有什麼意義?

扯了那麼多,結論還是那句話,在自己可以選擇的條件下:react-native 更適合前端領域的開發者,flutter 更適合原生領域的開發者,同時還和你想面試的崗位和產品有關係。


目前來看我會選擇用RN,但不會放棄對Flutter 的嘗試。

沒有其他原因,我已經有幾個成熟項目的RN開發經驗,所以線上選擇我目前還是更傾向於RN。另一方面,RN的技術棧更具親和力,沒辦法JS對於前端的親和力太強了。

從目前生態來看,RN的生態顯然更成熟些,一些問題基本都能找到解決方案,實在解決不了的通過橋接原生和自己修改源碼也能解決。Flutter 目前我自己還沒改源碼的能力,所以還得繼續研究下心裡才有底。

儘管有些大廠在用Flutter了,但是很多和跟當年用RN一樣,大部分是在一些詳情頁、個人頁、社區模塊在用,這樣保證了可進可退,而且大廠的自研能力很強,一言不合就定製了,這對中小型公司來說就成本比較高了,相對來看小公司更依賴於生態完善性上了,所以在這裡也提醒不要盲目追大廠的風。

Flutter 性能更好,而且跨平台上更徹底,這點是RN無法比擬的。RN 目前也在經歷新版本的重寫,未來發展成什麼樣也很難說。

無論選擇哪個,深入去用了,你會發現跨平台其實也沒那麼美了,你不僅要懂js/dart還要有原生開發能力。一次編寫,到處調試,各種環境的問題折騰的你會懷疑跨平台開發真的合算嗎?

選擇自己最趁手的能最快解決你的問題的技術棧,這是商業項目開發之本。


簡單說一下 @Aego 回答中我覺得可以商榷的地方:

React Native 基於 JS-Native Bridge 的渲染方案有著沒有辦法彌補的先天缺陷。性能上優化到 60 fps 都比較成問題,更不用提以後廣泛普及的 120 fps 的設備。

RN 之前的橋是完全用隊列非同步的,JS 線程並不會阻塞 UI 線程的 vsync。

對於普通的動畫場景,RN 在 17 年就給 Animated API 加了個 native driver 選項[1] ,這樣 JS 線程只需要對動畫做一個「聲明式描述」,然後序列化後扔過橋一次就好,這樣幀與幀之間的刷新都是 UI 線程直接跑,而不需要幀幀「過橋」讓 JS 線程來做「插值」,所以刷新率什麼的並沒有什麼影響。

可是舊架構問題在於,有一些強交互的場景(比如跟手拖拽)就需要同步阻塞更新怎麼辦?首先對於動畫問題你可以看看 Reanimated [2] 這個庫(btw Reanimated 2 已經是基於新架構得了),然後呢,我們來聊聊 RN 為了解決這個(以及其他)問題的「新架構」。

RN 在 18 年就提到了原有的橋架構不支持同步調用的問題[3] ,所以新架構的目的就是基於可同步調用的 JSI (JavaScript Interface)來重構原生模塊(TurboModules)、渲染(Fabric)與初始化(比如創建 Timer、Event Loop)等,使得 RN 可以完全去掉「橋」。相關的資料比較零散,主要的資料可以看 RN 團隊出去演講的 youtube 視頻,或者官方博客。社區文章儘管不一定準確但也可以湊合著看……(比如我隨手搜到了一篇對社區文章的中文翻譯[4])。

籠統得說,新架構的做法其實就類似大家熟悉的宿主環境(瀏覽器/Node)向 JS 引擎提供原生對象/函數的做法,JSI 在其中提供了這層宿主和引擎在編譯期鏈接用的 FFI(foreign function interface),通信其實就是在 C++ 之間調用函數,宿主對象(C++ 對象)和 JS 引擎的堆(JS 對象)可以互相持有引用互操作,因此不但支持同步調用,而且也不需要像以前的橋那樣在運行時序列化/反序列化,這帶來的性能的提升大概能有兩個數量級。以往的渲染(React VDOM 與 RN shadow tree 之間)其實也是反覆過橋得,現在都不用了。

而且你會發現新架構中 RN 的核心部分基本都用 C++ 重寫了,JSI 的兩端都是 C++,Yoga 布局引擎本來就是 C++,與原生模塊(JNI/OC++)的互操作部分現在是通過對 flow 做 codegen 來生成 C++。這一套零成本抽象下來,RN 的核心部分我覺得性能是不虛得。Dart 本身只是個帶著 GC 和 RTTI 的 AOT,並不是系統編程語言,我不知道 Flutter 除了 Skia 之外的部分有多少是 C++ 多少是 Dart 得。

Flutter 的設計則是完全自繪組件,Skia 渲染引擎本質上就相當於遊戲引擎的作用

Skia 是 Chrome/Android 都在用的二維圖形庫,Flutter 像個遊戲引擎是真的。

從跨平台的 UI 一致性的角度上看,Flutter 可以做到完全的一致性,而 RN 在點擊效果,陰影,甚至文本框之類的組件都無法做到不同平台間有著完全一致的行為。這點上對於有跨平台一致性強迫症需求的人來說,Flutter 幾乎可以說是唯一選擇。

Flutter 做得像遊戲引擎有圖形表達力強以及 self-contained 的優勢,但是對於跨平台開發來說就「仁者見智」了,「完全的一致性」真的是我們想要的嗎?iOS/Android 本來就有著不同的設計語言(滾動效果、點擊效果、系統 UI 組件),有不同的 distribution 版本,並且也會不斷演化。

你沒看 Flutter 為了「模擬」原生效果只好搞了兩套所謂的「平台物理」……然後系統 UI 組件還要全部自己造一遍主題輪子嗎……Flutter 的 iOS 主題美其名曰 Cupertino,結果人家 Cupertino 真的改一版設計,你的輪子一下老了一代又要重新畫了,委屈不委屈……(其實現在的看起來就挺過時挺慘得……)要不是你們 Mountain View 錢多人多真的燒不起啊。

RN 的哲學(官網博客[5])的第一點就是「要足夠 Native」,所以才用了 binding 的方式,Cupertino 一聲令下我們 Menlo Park 可能什麼都不用做最多 binding 一下 API 就好……這種做法可以很好的融入平台,方便復用以往的基礎設施,而且非常容易拓展新的平台支持:RN 的 Windows 和 macOS 版本也都不需要重新自己「畫畫」,而且還是大 Redmond[6] 做得呢……RN web 也是社區(Twitter)維護起來的,直接 binding 到 DOM 就完事了,跟以往的 web 基礎設施在一起工作毫無問題。FB 內部還有其他用 React binding 的平台。

而且還有一點是,RN 是真正的開源社區活躍,像 Releases 什麼都是社區在做,而 Flutter 就比較「吃 Google 飯」了……天哪你知道 Flutter 砸了多少人進去,RN 才多少人嗎?只能說 Google 真的錢多,像 Flutter 的 Hummingbird(Web Support)要做起來真的是一件相當吃力不討好的事情,真的錢多。

當然如果僅從個人小項目,對於性能要求不苛刻的情況下,確實 TypeScript 比較 Dart 還是有一些語言上的優勢,對於前端開發者來說可能更好上手一些。

理論上說,Dart 2 改成靜態類型有理由做到更好的性能,Dart 團隊也非常有實力,不過:

  1. 我確實從來沒有看到過任何像樣的數據可以證明「Dart 性能確實比 V8/JSC/Spidermonkey 這些 JIT 的 JS 引擎性能好」,歡迎拿數據打臉。
  2. 如果考慮 iOS 平台上 Dart 可以做 AOT 而 JS 只能解釋,那麼 Dart 在純運算("number crunching")來說沒優勢才是怪了。不過,這些性能能轉換到多少 App 的體驗就有待商榷了,畢竟 Dart 對 Flutter 可能是大頭,而 JS 對 RN 只是一種「輕量腳本」方案,並不承當主要的計算任務。

但 Dart 語言由於有豐富的語言特性(比如 extension)

你認真得?要不是劈柴砸錢 Flutter 這玩意早涼到不知哪裡去了。以前怎麼從沒見人用呢,Flutter 一出來你們反倒吹起語言來了?

Dart 是要特性沒特性,要品味沒品味。評論區說得好,狗家的語言都是「實用主義、大道至簡」吧反正唉……沒有正經學過點編程語言理論的不要來給我反駁這條,最煩的就是你們 :)

參考

  1. ^Using Native Driver for Animated https://reactnative.dev/blog/2017/02/14/using-native-driver-for-animated
  2. ^Reanimated https://docs.swmansion.com/react-native-reanimated/
  3. ^State of React Native 2018 - Architecture https://reactnative.dev/blog/2018/06/14/state-of-react-native-2018#architecture
  4. ^React Native 架構演進 https://zhuanlan.zhihu.com/p/142704512
  5. ^React Native Team Principles https://reactnative.dev/blog/2020/07/17/react-native-principles
  6. ^https://microsoft.github.io/react-native-windows/


https://t.cn/A62xuaBz 我們公司產品,完全用flutter寫的

我們在18年完成了第一版客戶端,用的的dcloud,為啥?別問,問就是小公司招不起原生。

受制於dcloud太多的性能問題以及各種使用限制(社區基本就是擺設,官方提問還要收3000大洋),我和當時的前端負責人以及老闆討論了前端的框架替代方案,當時前端4個人,3個人開始著手去調研,主要目標是rn,uniapp,flutter,weex。

我個人是後端出身,當時甚至想推薦xamarian。

調研的方向主要是從框架的控制項量、性能、社區活躍度、roadmap、背後靠山、語言難易度等緯度綜合評價。

第一輪pk後剩下rn和flutter。

於是我自己去嘗試了下,個人感覺,dart遠比js來得優雅,其次dart算得上是一門比較現代的語言,吸收了不少高級語言特性,又不失靈活。flutter為了更好的迎合前端,放棄了晦澀的mirror庫,這個算是比較遺憾的事情。

放棄rn有個主要的原因還是在性能上,當時為了做im,我們測試了各種控制項在大數據量的情況下的載入情況,rn是完敗給flutter的。

在經過2個月左右的調研和demo後我們最終還是選擇了flutter。

當然對著那5000+的issues當時是很擔心的。

過程中也遇到不少坑,好在通過設計調整和技術攻堅都解決差不多了。

重寫客戶端花了3個月時間,19年7月正式完成了版本替換,中間整個團隊背負了非常沉重的壓力。好在結果還是非常不錯的。目前除了偶發性的安卓版本兼容問題,以及webview不少坑之外,其他問題也隨著flutter本身版本升級以及社區各種大佬的解決方案逐一解決了。

我們後來還是招了2個原生做技術支持,主要是為了使用一些第三方控制項而作原生到flutter封裝工作。

目前我們團隊前端技術棧包含flutter,vue和原生,學習是痛苦的,但也是快樂的。前端的同學自己也清楚,掌握更多的技能技巧意味著什麼。我們這個團隊人不多,但技術氛圍還是不錯的,遇到困難還是會去不斷嘗試克服。

我覺得沒法從單方面去評價2個框架或者2門語言孰優孰劣,更多的還是需要結合團隊、項目、公司、地區的實際情況。,適合的才是最好的。


看現有資源:

如果是小團隊,甚至單幹,flutter可以嘗試一下,現在酷安上的獨立開發者,很多都轉flutter了。如果有其他react的項目關聯,rn也是不錯的選擇,雖然跟react不是一個東西,但是多多少少有些相近的地方。

對於工程實踐:

flutter的優勢在於,不用太熟悉現有h5系前端體系,弄個差不多的美工甚至不用美工,也能搞個像模像樣的app出來。

react的優勢在於有大量的社區資源和團隊資源可以用,只要不是還停留在jq時代的前端團隊,改造一下,也能開始擼app。

至於前景:

啥叫前景,做個項目,多說幾個月就進入穩定期,用不著考慮前景不前景,項目有了盈利能力,上原生、上隊伍、重構、重做都不是問題。項目不確定後續的話,怎麼省成本、怎麼快怎麼來。

要是說到個人前景的話,都玩唄,flutter、rn,加上uni-app、h5之類的,越多越好,藝不壓身。經驗豐富的意思就是踩的坑多填的坑多,技能精通的意思就是吃過見過被蹂躪過。

如果只能把精力投到一種上,個人建議投flutter,性能夠用,見效快,能跟風,吹牛都能多吹幾分鐘。


推薦閱讀:
相关文章