貝殼跨端之路——從 0 到 1 接入Flutter實戰

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一門新技術的興起,必定是爲了要解決現有技術解決不了的難題。跨端技術也遵循這一規律。傳統的純原生開發已經滿足不了日益增長的業務需求,而跨端技術的產生就是爲了要解決這一難題,具體表現在"},{"type":"text","marks":[{"type":"strong"}],"text":"動態化內容需求增大和業務需求變化快、開發成本變大"},{"type":"text","text":"這兩大方面。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"跨端技術的變革"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跨端最開始起源於瀏覽器。在App內使用 Native 的 Webview 來加載 Html5 頁面,這是移動端最開始的跨端實踐。接着,爲了使 Html5 頁面能夠更多地使用底層 SDK 或者補充性功能,Hybird開始流行起來。此後,各種各樣的跨端框架也隨之流行而來, 例如PhoneGap、AppCan。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2015年4月,Facebook發佈了React Native,主張“Learn once, write everywhere”,採用Javascript 開發 + 原生渲染技術,類似的還有 Weex 和快應用。同年 Flutter 也發佈了,不過當時關注的人較少,直到 2018 年的1.0 版本發佈,關注和使用的人才多了起來。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"貝殼決定建設跨端能力"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2018年,由於貝殼公司內部業務發展較快、需求較多,貝殼開始做平臺化能力建設,但因缺乏跨端能力,貝殼開始考慮跨端能力方面的建設。綜合了團隊構成、業務特點、團隊經驗以及業界的動態等因素,貝殼成立了Flutter架構小組(以下統稱小組)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之後,趙宏偉帶着小組成員開啓了貝殼跨端探索之旅。那麼在這場旅途中,貝殼在接入Flutter的過程中都進行了哪些探索呢?爲此,InfoQ邀請到了Flutter架構小組負責人趙宏偉以及小組成員肖鵬、裴偉來跟大家一起聊聊貝殼的Flutter接入實踐。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相比其他跨端框架,Flutter雖有一定的優勢,但剛開始,貝殼並沒有直接就選用Flutter。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"“當時組內準備考慮一些跨平臺的方案做一些小的嘗試和調研。後來,到2018年底,Flutter1.0 發佈,小組開始對跨端方案進行了深度調研。起初,組內是對RN和Flutter做調研,FE團隊(貝殼前端團隊)負責Weex的調研和使用。”趙宏偉回憶到。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"經過調研之後,Flutter架構小組首先放棄了RN。原因如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.渲染通信路徑長。React Native的邏輯層和UI的描述層都在js;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.React Native跨端技術的實現思路是適配,兩個移動端(iOS和Android)仍然存在很多組件差異;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3.React Native的頁面層級問題;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4.動態化需求不多;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5.有一些公司宣佈放棄React Native,以及React 許可的一些問題,不確定性較多。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於Weex,貝殼前端同學在某些業務上做了部分實驗,得到的結論是「效果一般」,沒有對他們整個前端的行爲有多大改變,因此也放棄了Weex。而對於Flutter,首先Flutter主打的自渲染,UI到邏輯都是自身一套;其次Flutter基於對應平臺獨立編譯,更適合對應平臺的運行,並且支持多平臺;最後,Flutter支持JIT和UT模式,既能兼顧開發效率,也能兼顧運營效率。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基於以上調研與考慮,貝殼最終選擇了Flutter。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"選定跨端框架,接下來就是爲接入做準備了。我們瞭解到貝殼在接入Flutter的過程中,整個項目經歷了3個階段。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"正式開啓跨端之旅"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"據趙宏偉透露,第一個階段他們的目標是快速落地驗證。在此階段中,他們也遇到了兩個難題。第一是如何保證既能進行Flutter開發,又不影響非Flutter開發人員,並且官方的既有工程集成方案對他們的工程侵入性較大,如果按照最原始的方式打包效率也比較低,因此他們設計了自己的集成方案; 第二是Flutter層面需要組件化,小組內部也設計了組件化方案來解決快速落地問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在以上問題得到解決之後,他們在部分業務進行快速實驗,“當時的業務場景下反饋還不錯。”趙宏偉說。接下來就來到第二階段。在這一階段中,他們更全面注重開發和用戶體驗。因此,他們將建設分爲了三部分。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一部分是Flutter在持續集成方面建設;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二部分是業務開發核心基礎庫能力建設(標準化);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三部分是容災降級及穩定性方面的建設。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"完成了以上三部分的建設,項目就到了第三階段,貝殼Flutter架構組開始進行多端一體化能力建設。2020年,小組針對Flutter for web做了一些研究,並做出了貝殼Flutter For web的容災降級系統。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"“今年(2021年)我們一直在研究Flutter多端一體化方案, 官方也在2.0中主推了web方向的應用,目前主要是在優化Flutter For web的應用體驗,包括加載和部署優化,內存優化,三端一體化的核心基礎補充以及監控埋點能力補充。我們內部的監控系統一部分Web頁面也是使用Flutter 來開發的。”趙宏偉說。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"截止到採訪時,貝殼80%(24款)的App已經接入了Flutter。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當提到這麼多App接入Flutter之後帶給貝殼的收益時,趙宏偉興奮地說:“效率,這個是我們最直觀的感覺,整個2020年貝殼所有業務線都參與過Flutter,一致的感受都是效率,以前兩個人開發,現在一個人就可以完成。”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了最直觀的效率上的提升,貝殼還做了一整套的標準化UI組件(UI組件160+,業務組件30+),這是屬於他們的技術創新。並且參與此項目的成員在Flutter 容器、Aop 編譯、監控、UI自動化和動態化等相關研究中還積累了大量的技術經驗,進一步提升了個人技術能力。此外,據小組成員蕭鵬描述,他們還將這些UI自動化的創新技術整理成文章進行了輸出,把創新技術分享給更多有需要的開發者們。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Flutter的成功接入,雖然讓貝殼在跨端能力方面的建設得到了很大的提升,但有些問題,目前小組仍沒有較好的解決方案,首先就是內存問題。當提到內存時,趙宏偉略顯苦惱。“除了容器自身的內存,還有圖片的一些邊界場景和釋放,以及一些三方圖片庫存在圖片釋放和圖片過大的Crash問題。”趙宏偉說。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"針對這一問題,貝殼採用了共享引擎和圖片紋理方案來管理Flutter 圖片緩存,雖然得到了很大的改善,但當業務場景中出現多容器時,容器消耗內存仍然不小。再者是Platform View和渲染問題,Flutter在Platform View上有一部分內存和適配問題。據瞭解,這些問題需要深入到引擎內部,更改成本較高,貝殼便沒有過多的干預,而是選擇了積極適配新版。最後是動態化問題,在iOS側,小組內部沒有比較好的動態化方案,目前只保證維護好性能和低成本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了以上的一些問題,據趙宏偉透露,貝殼在引入Flutter 之後,還產生了一些新問題。主要體現在以下幾點:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一、集成問題"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先是在第一階段的集成方案不夠完善,RD反饋調試較爲困難,QA反饋打包時間長,錯誤率高。其次是配置問題,因小組內部在Flutter SDK上做了定製,所以配置起來就比較困難;再加上多個項目的Flutter SDK版本不一致,開發人員需要手動組合Flutter tools和Flutter SDK,這一過程增加了成本;還有在打包的時候,需要先將項目在制定打包機上打包,再在主包上打包,這個時間就比較長。於是,他們就重新做了一版集成方案,並開發了Flutter SDK自動化集成更新方案,目前在Flutter、Dart編譯部分就如同一個target任務,和其他代碼一起進行併發編譯,大大提高了效率。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"        "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"二、包大小問題"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在C端落地時候,貝殼更加關注包大小。貝殼當時接入的Flutter1.12.13,其包大小一度達到30MB,業務方緊急要求瘦身,因此Flutter架構小組通過改造Flutter編譯器以及Flutter Engine對Flutter產物數據段做了分離壓縮,可以內置,可以遠程下發,並去掉符號表和無用文件,將包體積從30MB縮小到17MB。在後續的規劃中,趙宏偉說:“我們會結合Flutter for Web 方案,在遠程下發失敗後動態轉到for Web 頁面,提高頁面打開成功率,保證業務正常流轉。”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當在使用Flutter for Web時,Flutter會將所有的業務打包成一個整包,但對於單獨訪問一個頁面的場景,加載就會比較慢,爲解決這一問題,小組對整個包進行了拆分,並把資源上傳到CDN來解決加載問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"三、異常監控問題"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在做異常監控時,在瘦身模式下,獲取的堆棧是沒有辦法被解析的,很多都是系統堆棧問題,沒有辦法進一步解決,並且很多都是沒用的堆棧,無法將問題細緻化。針對這一問題,貝殼做了一套後端的分流解析服務。這套服務首先是將Flutter Exception進行符號化,然後對堆棧進行分析,去掉無用和白名單內的堆棧行後進行歸因,如果歸不到業務方,再採取頁面分流的方式,來達到異常監控的效果。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"四、圖片導致的內存問題"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Flutter本身內存方面消耗比較嚴重,而自己又是一套獨立的圖片緩存,因此,在大圖片場景下,加上Native的圖片內存佔用,整體圖片導致的內存問題比較多。面對這一問題,貝殼採用了外接紋理方案,讓Flutter和Native共享一份圖片緩存,以及在大圖場景下使用外接紋理方案進行邊界處理,這對內存都做了比較好的優化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了以上的一些問題,還有一個比較大的挑戰。“在引入Flutter之後,當面對產品經理的提出的一些交互效果,Flutter本身技術能力又無法支持時,就需要小組內部去找其他的解決方案來解決,可能會考慮原生,或同時使用原生安卓來做。”小組成員裴偉補充道。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然產生了以上這些新問題,但好在小組內部也提出了相應的解決方案。同時,貝殼也一直在尋找更優的解決方法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"貝殼Flutter的成功接入也讓貝殼開發團隊的開發效率得到了跨級別的提升。但在此過程中,貝殼也遭遇到過一個“靈魂拷問”—— 效率or體驗?"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"一個永恆的話題—— 要效率,還是要體驗?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 一款產品,一個App被生產出來,就一定是爲了滿足用戶的某種需求,被人們使用的,因此用戶體驗要好。而對一個公司而言,一個高效率的組織形式也非常重要,高效的開發可爲公司解決人力、財力等各方面的問題。當問到在接入Flutter的過程中,貝殼是如何權衡效率和體驗的問題時,趙宏偉的回答是比較明確的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"“像直播、視頻、地圖這一類的,不建議使用Flutter,其他的在使用Flutter時,該提效的就提效,該注重體驗就注重體驗。當然每個App也有自己的着重方向,要根據自己的場景去捨棄效率或者體驗。”趙宏偉表示。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在面對貝殼的業務場景時,貝殼引入Flutter的關鍵目標就是要解決開發效率問題。因此,爲了進一步提高開發效率,貝殼也做了接下來的打算。首先是研究多端一體化,即將Flutter 能夠應用到web上,包括加載、部署優化、內存優化,以及三端一體化的核心基礎補充和監控埋點能力補充。目前也在研究中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其次是在應用上,貝殼內部會有一些Native 和 Html5 的業務要做。Html5 主要面向站外,貝殼希望能夠用一套代碼解決三端需求,這樣提效會更進一步。趙宏偉接着說:“我們可能會考慮Flutter 在 VR渲染上的一些應用,不過目前還在設想階段。”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除此之外,貝殼對新的OS,比如 鴻蒙,在兼容模式下也做了適配,並開始着手做了一些準備。“當然也要配合公司的產品策略,是否大範圍的適配跟進。”趙宏偉補充到。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"寫在最後"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本次的Flutter接入實戰,不僅解決了貝殼的“效率提升”問題,還見證了貝殼從0到1的跨端能力建設。從最初不夠完善的基礎建設,到引入Flutter過程中所遇到的各種困難,貝殼都在實踐過程中努力尋找解決方案並構建了一些屬於貝殼的創新技術。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章