Flutter混合工程改造實踐

閒魚技術發表於2018-07-06

作者:閒魚技術-字平

背景

閒魚技術團隊於2018年上半年率先引入了Flutter技術嘗試實現客戶端開發的統一,併成功改造和上線了複雜的商品詳情業務。這一過程中,由於原有的iOS和安卓工程都已相當龐大,如何將Flutter無縫橋接到這些大工程並保證開發效率不受影響成為優先要解決的問題。
本文針對專案實踐人員給出了一種通用的工程改造方案,希望為準備轉型Flutter的團隊提供參考。

問題

Flutter的工程結構比較特殊,由Flutter目錄再分別包含Native工程的目錄(即ios和android兩個目錄)組成。預設情況下,引入了Flutter的Native工程無法脫離父目錄進行獨立構建和執行,因為它會反向依賴於Flutter相關的庫和資源。

Flutter混合工程改造實踐

典型的Flutter目錄結構

很顯然,在擁有了Native工程的情況下,開發者不太可能去建立一個全新的Flutter工程重寫整個產品,因此Flutter工程將包含已有的Native工程,這樣就帶來了一系列問題:
__1).構建打包問題:__引入Flutter後,Native工程因對其有了依賴和耦合,從而無法獨立編譯構建。在Flutter環境下,工程的構建是從Flutter的構建命令開始,執行過程中包含了Native工程的構建,開發者要配置完整的Flutter執行環境才能走通整個流程;
__2).混合編譯帶來的開發效率的降低:__在轉型Flutter的過程中必然有許多業務仍使用Native進行開發,工程結構的改動會使開發無法在純Native環境下進行,而適配到Flutter工程結構對純Native開發來說又會造成不必要的構建步驟,造成開發效率的降低。

目標

針對以上問題,我們提出了以下的改造目標,力求最小化Native工程對Flutter相關檔案的依賴,使得:
1).Native工程可以獨立地編譯構建和除錯執行,進而最大限度地減少對相關開發同學的干擾並使打包平臺不再依賴Flutter環境及相關流程;
2).Native工程處在Flutter環境中時(即作為ios或android子目錄)能夠正確依賴相關庫和檔案,正常執行各類Flutter功能,如dart程式碼的構建,除錯,hot reload等,保證Flutter環境下開發的正確性。

方案的制定

兩種模式

首先定義Native工程處於獨立目錄環境下稱為Standalone模式,處於Flutter目錄下稱為Flutter模式。目標中純Native開發或平臺打包就處於Standalone模式,Flutter對開發人員和打包平臺來說是透明的存在,不會影響構建與除錯;而Flutter的程式碼則在Flutter模式進行開發,其相關庫的生成,編譯和除錯都走Flutter定義的流程。

Flutter混合工程改造實踐

兩種模式

理清依賴

從上面的定義來看,改造的核心就是把Standalone模式提取出來,那麼就要理清Standalone模式對Flutter的依賴,並將其提取成第三方的庫,資源或原始碼檔案。以iOS為例,通過閱讀Flutter構建的原始碼,可知Xcode工程對Flutter有如下依賴:
1).App.framework:dart業務原始碼相關檔案
2).Flutter.framework:Flutter引擎庫檔案
3).pubs外掛目錄及用於索引的檔案:Flutter下的外掛,包括各種系統的和自定義的channels
4).flutter_assets:Flutter依賴的靜態資源,如字型,圖片等

依賴引入的策略

改造過程中閒魚嘗試過兩種依賴引入策略,以下分別進行闡述。
1).本地依賴: 通過修改Flutter構建流程將其庫檔案,原始碼和資源直接放置到Native工程的子目錄中進行引用,以iOS為例,就是將Flutter.framework及相關外掛等做成本地的pod依賴,資源也複製到本地進行維護。 由此,Standalone模式便具備了獨立構建和執行的能力,對於純Native開發人員來說Flutter只是一些二方庫與資源的合集,無需關注。 而在Flutter模式下,dart原始碼的構建流程不變,不影響編譯和除錯;同時由於是本地依賴,Flutter模式下的各種改動也實時可以同步到Native工程的子目錄中,提交修改後Standalone模式也就擁有了最新的Flutter相關功能。
__優點:__Flutter相關內容的改動同步到Standalone模式也比較方便;
__缺點:__需要對Flutter原有的構造流程進行稍嫌複雜的改動,並且與後續的Flutter程式碼合併會有衝突,且Native工程與Flutter的內容還是耦合在本地不夠獨立。
2).遠端依賴: 遠端依賴的想法是將Flutter所有依賴內容都放在獨立的遠端倉庫中,在Standalone模式下引用遠端倉庫中的相關資源,原始碼和庫檔案,Flutter模式下的構建流程和引用方式則不變。
__優點:__對Flutter自身的構建流程改動較少並且較徹底第解決了本地耦合的問題;
__缺點:__同步的流程變得更繁瑣,Flutter內容的變動需要先同步到遠端倉庫再同步到Standalone模式方能生效。 PS. 閒魚最終選擇了這個策略。

Flutter混合工程改造實踐

遠端依賴

改造的實現

目錄的組織

Flutter模式下父工程目錄下的ios和android的子目錄分別包含對應的Native工程,程式碼管理上子工程可以使用git的submodule形式,保證目錄間的獨立。

遠端依賴的實現

在Standalone模式下,Flutter的依賴內容都指向遠端倉庫中的對應檔案,而在Flutter模式下依賴的方式不變。
1)向Standalone模式同步Flutter的變更
由於遠端依賴的問題是同步變動比較麻煩,為此閒魚開發了一系列指令碼工具使該過程儘量自動完成。 假設Flutter的內容(可能是業務原始碼,引擎庫或某些資原始檔)發生變化,那麼在Flutter模式下構建結束後,指令碼會提取生成好的所有依賴檔案拷貝到遠端倉庫,提交併打tag,然後依據打出的tag生成新的遠端依賴說明(比如iOS下的podspec),最後在Standalone模式下修改Flutter的依賴至最新的版本,從而完成整個同步過程。

Flutter混合工程改造實踐

同步流程

2)同步的時機
建議在提測及灰度期間,每次Flutter業務的提交都能夠觸發同步指令碼的執行和app打包;開發期間保持每日一次的同步即可。

總結

為解決引入Flutter後的工程適配問題,我們抽取了Flutter的相關依賴放到遠端供純Native工程進行引用,從而保證了Flutter與純Native開發的相互獨立與並行執行。
該方案已在閒魚施行了幾個版本,並反向輸出給了Flutter團隊,為其後續的hybrid工程組織計劃提供了方向和參考。同時,相信該方案也可以為轉型Flutter的團隊提供幫助,當然專案間的差異也會導致方案的不同,因此如有更好的方法和意見也期望多多交流!
最後,閒魚技術團隊廣招各類方向的達人,無論你是精通移動端,前端,後臺,還是機器學習,音視訊,自動化測試等,都歡迎投遞簡歷加入我們,一同用技術改善生活!

簡歷投遞:guicai.gxy@alibaba-inc.com

相關文章