1.2.3 方案的制定
1.兩種模式
首先将Native 工程處于獨立目錄環境下稱為Standalone 模式,處于Flutter 目錄下稱為Flutter 模式。純Native 開發或平台打包就處于Standalone模式,Flutter 對開發人員和打包平台來說是透明的,不會影響建構與調試。而Flutter 的代碼則在Flutter 模式下進行開發,其相關庫的生成、編譯和調試都執行Flutter 定義的流程,如圖1-13 所示。

圖1-13 兩種工程模式
2.厘清依賴
從模式的定義來看,既然改造的核心就是把Standalone 模式提取出來,那麼就要厘清Standalone 模式對Flutter 的依賴,并将其提取成第三方的庫、資源或源碼檔案。以iOS 為例,通過閱讀Flutter 建構的源碼,可知Xcode工程對Flutter 有如下依賴:
1)App.framework:Dart 業務源碼相關檔案。
2)Flutter.framework:Flutter 引擎庫檔案。
3)pubs 插件目錄及用于索引的檔案:Flutter 下的插件,包括各種系統的插件和自定義的channels(橋接通道)
4)flutter_assets:Flutter 依賴的靜态資源,如字型和圖檔等。
3.依賴引入的政策
在改造過程中,閑魚嘗試過兩種依賴引入政策,下面分别進行闡述。
(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 模式下的建構流程和引用方式不變,如圖1-14 所示。
優點:對Flutter 自身的建構流程改動較少,較徹底地解決了本地耦合的問題。
缺點:同步的流程變得更煩瑣,Flutter 内容的變動需要先同步到遠端倉庫後再同步到Standalone 模式方能生效。
圖1-14
1.2.4 改造的實作過程
1.目錄的組織
在Flutter 模式下,父工程目錄下的iOS 和Android 的子目錄分别包含對應的Native 工程。在代碼管理上,子工程可以使用Git 的Submodule 形式,保證目錄間的獨立。
2.遠端依賴的實作
在Standalone 模式下,Flutter 的依賴内容都指向遠端倉庫中的對應檔案,而在Flutter 模式下依賴的方式不變。
(1)向Standalone 模式同步Flutter 的變更。由于遠端依賴的問題是同步變動比較麻煩,為此閑魚開發了一系列腳本工具,使該過程盡量自動完成。假設Flutter 的内容(可能是業務源碼、引擎庫或某些資源檔案)發生變化,那麼在Flutter 模式下建構結束後,腳本會提取生成好的所有依賴檔案并将其複制到遠端倉庫,送出并打标簽,然後依據打出的标簽生成新的遠端依賴說明(如iOS 下的podspec 檔案),最後在Standalone 模式下将Flutter 的依賴修改至最新的版本,進而完成整個同步過程,如圖1-15 所示。
圖1-15
(2)同步的時機
建議在提測及灰階期間,每次Flutter 業務的送出都能夠觸發同步腳本的執行和App 打包;在開發期間,保持每日一次的同步即可。
為解決引入Flutter 後的工程适配問題,閑魚抽取了Flutter 的相關依賴放到遠端供純Native 工程進行引用,進而保證了Flutter 與純Native 開發的互相獨立與并行執行。
該方案已在閑魚施行了幾個版本,并反向輸出給了Flutter 團隊,為其後續的hybrid 工程組織計劃提供了方向和參考。同時,相信該方案也可以為轉型Flutter 的團隊提供幫助,雖然項目間的差異也會導緻方案的不同,但是實施的思路依然有借鑒價值。