互聯網首發 | 閒魚程序員公開多年 Flutter 實踐經驗

簡介

flutter-boot核心解決了混合開發模式下的兩個問題:flutter混合開發的工程化設計和混合棧。那flutter-boot是如何解決的呢?

首先在工程化設計的問題上,flutter-boot建立了一套標準的工程創建流程和友好的交互命令,當流程執行完成後,即擁有了混合開發的標準工程結構,這一套工程結構能夠幫助我們同時擁有flutter和native(原生)兩種開發視角,本地flutter開發和雲端flutter構建兩種flutter集成模式,其效果如圖:

 

另外在混合棧的問題上,flutter-boot能自動注入混合棧依賴,同時將核心的混合棧接入代碼封裝後注入到原生工程內,在用戶按提示插入簡單幾行模版代碼後,即可看到混合棧的效果。 使用flutter-boot搭建的混合工程,開箱即可使用,接下來讓我們瞭解下flutter-boot解決這些問題的詳細過程。

開源地址

https://github.com/alibaba-flutter/flutter-boot

工程化設計

瞭解官方的Add Flutter to existing apps項目

在瞭解flutter-boot的工程化設計細節前,我們需要對Google官方提供的Add Flutter to existing apps方案有一個初步的瞭解。Add Flutter to existing apps項目會引導我們以module的形式創建flutter,module形態的flutter的工程結構如下:

 

在官方的工程結構下,.ios和.android是運行flutter時的模版工程,在flutter工程目錄下運行時即通過這兩個工程來啓動應用。那我們如何讓原生工程和產生關聯呢?這裏的關聯會分成三個部分,分別是flutter的framework,flutter的業務代碼,和flutter的插件庫。其中flutter插件庫分成 flutter plugin native(即插件原生代碼)和flutter plugin dart(即插件的dart代碼)兩個部分。這四部分的差異在於:

 

因此flutter framework只需要在依賴管理中聲明即可,flutter plugin native可以直接以源碼的方式集成,flutter plugin dart只有在被業務代碼引用時纔有效,因此和業務代碼一樣,需要支持dart代碼的調試模式和發佈模式,因此dart代碼的關聯會侵入到app的構建環節,根據app構建的模式來決定dart代碼的構建模式。

具體的實現,拿iOS來舉例,我們會在podfile文件中增加一個自定義的ruby腳本podfilehelper的調用,podfilehelper會聲明flutter framework的依賴,聲明flutter plugin native的源碼引用,同時聲明業務代碼的路徑。接下來會介入構建流程,在xcode的build phase內加入shell腳本xcode_backend的調用,xcode_backend會根據當前構建模式,來產出dart構建產物。

flutter-boot的補充

對於官方的混合工程項目,我們在體驗後發現有如下的問題:

  1. 文件或配置的添加爲手動添加,流程較長。
  2. 不支持在flutter倉庫下運行原生工程。
  3. 不支持flutter以獨立代碼倉庫部署時的遠端機器構建。

因此在flutter-boot腳手架中,爲了解決這些問題,我們把混合工程的部署分爲create,link,remotelink,update四個過程。

★ create

create過程目的在於幫助我們搭建一個flutter module,包括flutter module的創建和git倉庫的部署,flutter module創建命令調用前,我們會做基礎的檢查來讓工程位置和命名的規範滿足官方的條件。在git倉庫部署時,我們會在gitignore中忽略部分文件,同時我們會對倉庫的狀態進行檢查,在倉庫爲空時,直接添加文件,在倉庫非空時,會優先清理倉庫。

★ link

link過程目的在於關聯本地的原生工程和flutter工程。關聯的過程中,我們會先請求獲取flutter工程的地址和原生工程的地址,然後我們將上面提到的需要手動集成的部分通過腳本的方式自動集成;爲了獲得flutter開發視角(即flutter工程下運行原生工程),我們將原生工程進行了軟鏈接,鏈接到flutter工程的ios目錄和android目錄,flutter在運行前會找到工程下的ios或android目錄然後運行,在flutter工程下運行iOS工程會存在一個限制,即iOS工程的target需要指定爲runner,爲了解決這個問題,我們將原生工程的主target進行了複製,複製了一份名爲runner的target。

同時,爲了支持遠程構建的模式,我們flutter倉庫本地路徑的聲明根據構建模式進行了區分,封裝在自定義的依賴腳本中,例如在iOS工程內,我們會添加fbpodhelper.rb腳本文件。然後將flutter倉庫本地路徑添加到了配置文件fbConfig.local.json中。

★ remotelink

update remotelink過程目的在於遠端構建模式下,能夠獲取flutter倉庫的代碼,並在遠端機器上進行構建。在遠端構建模式下,我們會侵入依賴管理的過程,在依賴獲取時,拉取flutter倉庫的代碼,將代碼放置在原生工程的.fbflutter目錄下,並將該目錄聲明爲flutter倉庫本地路徑,拉取flutter代碼並進行本地部署的過程,我們稱之爲update過程。

這樣在遠端構建時就能和本地構建如出一轍。 那遠端模式和本地模式如何區分呢?爲了區分遠端模式與本地模式,我們將遠端的flutter倉庫信息記錄在fbConfig.json,同時在gitignore中忽略fbConfig.local.json文件,這樣只需要初始化混合工程的工程師運行一次remotelink,其他的開發協同者將不用關注遠端構建的配置流程。

★ init

爲了方便快速搭建,我們提供了一個命令集合,命名爲init,我們將必備的環節以命令行交互的模式集成在了init命令中。

混合棧

混合棧是閒魚開源的一套用於flutter混合工程下協調原生頁面與flutter頁面交互的框架,目前是混合開發模式下的主流框架。在混合棧開源後,我們關注到大量開發者在集成混合棧時會產生各種環境配置或代碼添加導致的集成問題。因此我們決定提供一套快速集成的方案。要做到快速集成我們面臨兩個問題:

  1. flutter和混合棧的版本兼容;
  2. 混合棧demo代碼封裝及插入。

版本兼容問題

目前混合棧發佈版本爲0.1.52,支持flutter 1.5.4。當flutter升級時混合棧勢必要進行適配,即我們集成的混合棧版本也需要變更。因此我們將混合棧的版本配置通過文件進行維護,記錄當前flutter所需要的混合棧版本。在初版的flutter-boot中,我們限定了混合棧的版本號,在新版本混合棧發佈時,我們將開放版本選擇的功能。

代碼封裝及插入問題

在調研了混合棧的使用過程後,我們將混合棧需要的demo代碼分成了四個部分:

  1. flutter引擎的託管;
  2. 頁面路由的配置 ;
  3. demo形式的dart頁面 ;
  4. 原生的測試跳轉入口。

★ flutter引擎的託管

引擎的託管我們依賴於應用的初始化,由於初始化過程隨着應用的複雜程度提升而提升,因此目前我們提供了一行代碼作爲接口,使用者在應用初始化時加入這一行代碼即可完成託管。

★ 頁面路由的配置

demo形式的dart頁面,路由配置即路由到某個標識符時,flutter或原生頁面需要識別並跳轉相應頁面。路由的配置需要在原生和flutter兩側進行部署。在原生側,我們將混合棧的demo路由代碼進行了精簡,然後添加在了原生工程的固定目錄下。由於iOS僅添加代碼文件是不會被納入構建範圍的,因此我們封裝了一套iOS側的代碼添加工具來實現文件的插入。在flutter側我們對main.dart文件進行了覆蓋,將帶有路由邏輯的main.dart集成進來,同時提供了demo dart頁面的創建邏輯。

★ 原生的測試跳轉入口

爲了方便使用者快速看到混合工程的跳轉模式,我們在iOS和android雙端封裝了一個入口按鈕和按鈕的添加過程,使用者在測試的頁面手動加入一行代碼,即可看到跳轉flutter的入口。

效果

在使用flutter-boot前,開發者可能要花費數天來進行混合工程搭建,現在,使用者只需要調用一個命令,加入兩行代碼即可完成混合工程的搭建,大大降低了開發者的開發成本。但flutter-boot的使命還未達成,我們期望使用者能更加流暢的進行flutter開發,未來我們會優化多人協同的開發流程,完善持續集成環境的搭建,讓使用者擁有更佳的開發體驗。

Flutter的深入進階教程

它們包括瞭如何低成本實現Flutter富文本、設計一個高準確率的Flutter埋點框架、Flutter外接紋理、可定製化的Flutter相冊組件等等深入進階內容。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章