Picasso:開啟大前端的未來

美團技術團隊發表於2019-03-01
        “道生一,一生二,二生三,三生萬物。” —— 《道德經》

Picasso是大眾點評移動研發團隊自研的高效能跨平臺動態化框架,經過兩年多的孕育和發展,目前在美團多個事業群已經實現了大規模的應用。

Picasso源自我們對大前端實踐的重新思考,以簡潔高效的架構達成高效能的頁面渲染目標。在實踐中,甚至可以把Native技術向Picasso技術的遷移當做一種效能優化手段;與此同時,Picasso在跨越小程式端和Web端方面的工作已經取得了突破性進展,有望在四端(Android、iOS、H5、微信小程式)統一大前端實踐的基礎之上,達成高效能大前端實踐,同時配合Picasso佈局DSL強表達能力和Picasso程式碼生成技術,可以進一步提升生產力。

客戶端動態化

2007年,蘋果公司第一代iPhone釋出,它的出現“重新定義了手機”,並開啟了移動網際網路蓬勃發展的序幕。Android、iOS等移動技術,打破了Web應用開發技術即將一統江湖的局面,之後海量的應用如雨後春筍般湧現出來。移動開發技術給使用者提供了更好的移動端使用和互動體驗,但其“靜態”的開發模式卻給需要快速迭代的網際網路團隊帶來了沉重的負擔。

客戶端“靜態”開發模式

客戶端開發靜態模式

客戶端開發技術與Web端開發技術相比,天生帶有“靜態”的特性,我們可以從空間和時間兩個維度來看。

從空間上看需要整合釋出,美團App承載業務眾多,是跨業務合流,橫向涉及開發人員最多的公司,雖然開發人員付出了巨大的心血完成了業務間的元件化解耦拆分,但依然無可避免的造成了以下問題:

  1. 編譯時間過長。 隨著程式碼複雜度的增加,整合編譯的時間越來越長。研發力量被等待編譯大量消耗,整合檢查也變成了一個巨大的挑戰。
  2. App包體增長過快。 這與迅猛發展的網際網路勢頭相符,但與新使用者擴充和業務迭代進化形成了尖銳矛盾。
  3. 執行時耦合嚴重。 在整合釋出的包體內,任何一個功能元件產生的Crash、記憶體洩漏等異常行為都會導致整個App可用性下降,帶來較大的損失。
  4. 整合難度大。 業務線間程式碼複用耦合,業務層、框架層、基礎服務層錯綜複雜,需要拆分出相當多的相容層程式碼,影響整體開發效率。

從時間上看需要集中釋出,線上Bug修復鬚髮版或熱修復,成本高昂。新功能的新增也必須等待統一的發版週期,這對快速成長的業務來說是不可接受的。App開發還面臨嚴重的長尾問題,無法為使用老版本的使用者提供最新的功能,嚴重損害了使用者和業務方的利益。

這種“靜態”的開發模式,會對研發效率和運營質量產生負面影響。對於傳統的桌面應用軟體開發而言,靜態的研發模式也許是相對可以接受的。但對於業務蓬勃發展的移動網際網路行業來說,靜態開發模式和敏捷迭代釋出需求的矛盾日益突出。

客戶端動態化的趨勢

如何解決客戶端“靜態”開發模式帶來的問題?

業界最早給出的答案是使用Web技術

但Web技術與Native平臺相比存在效能和互動體驗上的差距。在一些效能和互動體驗可以妥協的場景,Web技術可以在定製容器、離線化等技術的支援下,承載運營性質的需要快速迭代試錯的頁面。

另一個業界給出的思路是優化Web實現

利用移動客戶端技術的靈活性與高效能,再造一個“標準Web瀏覽器”,使得“Web技術”同時具有高效能、良好的互動體驗以及Web技術的動態性。這次技術浪潮中Facebook再次成為先驅,推出了React Native技術(簡稱RN)。不過RN的設計取向有些奇怪,RN不相容標準Web,甚至不為Android、iOS雙端行為對齊做努力。產生的後果就是所有“吃螃蟹”的公司都需要做二次開發才能基本對齊雙端的訴求。同時還需要盡最大努力為RN的相容性問題、穩定性問題甚至是效能問題買單。

而我們給出的答案是Picasso

客戶端開發靜態模式

Picasso另闢蹊徑,在實現高效能動態化能力的同時,還以較強的適應能力,以動態頁面、動態模組甚至是動態檢視的形式融入到業務開發程式碼體系中,贏得了許多移動研發團隊的認同。

Picasso框架跨Web端和小程式端的實踐也已經取得了突破性進展,除了達成四端統一的大前端融合目標,Picasso的佈局理念有望支援四端的高效能渲染,同時配合Picasso程式碼生成技術以及Picasso的強表達能力,生產力在大前端統一的基礎之上得到了進一步的提升。

Picasso動態化原理

Picasso應用程式開發者使用基於通用程式語言的佈局DSL程式碼編寫佈局邏輯。佈局邏輯根據給定的螢幕寬高和業務資料,計算出精準適配螢幕和業務資料的佈局資訊、檢視結構資訊和文字、圖片URL等必要的業務渲染資訊,我們稱這些檢視渲染資訊為PModel。PModel作為Picasso佈局渲染的中間結果,和最終渲染出的檢視結構一一對應;Picasso渲染引擎根據PModel的資訊,遞迴構建出Native檢視樹,並完成業務渲染資訊的填充,從而完成Picasso渲染過程。需要指出的是,渲染引擎不做適配計算,使用佈局DSL表達佈局需求的同時完成佈局計算,既所謂“表達即計算”。

從更大的圖景上看,Picasso開發人員用TypeScript在VSCode中編寫Picasso應用程式;提交程式碼後可以通過Picasso持續整合系統自動化的完成Lint檢查和打包,在Picasso分發系統進行灰度釋出,Picasso應用程式最終以JavaScript包的形式下發到客戶端,由Picasso SDK解釋執行,達成客戶端業務邏輯動態化的目的。

在應用程式開發過程中,TypeScript的靜態型別系統,搭配VSCode以及Picasso Debug外掛,可以獲得媲美傳統移動客戶端開發IDE的智慧感知和斷點除錯的開發體驗。Picasso CI系統配合TypeScript的型別系統,可以避免低階錯誤,助力多端和多團隊的配合;同時可以通過“相容計算”有效的解決能力支援的長尾問題。

Picasso佈局DSL

Picasso針對移動端主流的佈局引擎和系統做了系統的對比分析,這些系統包括:

  1. Android開發常用的https://developer.android.google.cn/guide/topics/ui/layout/linear“>LinearLayout。
  2. 前端及Picasso同類動態化框架使用的FlexBox
  3. 蘋果公司主推的AutoLayout

其中蘋果官方推出的AutoLayout缺乏一個好用的DSL,所以我們直接將移動開發者社群貢獻的
AutoLayout DSL方案列入對比。

首先從效能上看,AutoLayout系統是表現最差的,隨著需求複雜度的增加“佈局計算”耗時成指數級的增長。FlexBox和LinearLayout相比較AutoLayout而言會在效能表現上有較大優勢。但是LinearLayout和FlexBox會讓開發者為了佈局方面需要的概念增加不必要的檢視層級,進而帶來渲染效能問題。

從靈活性上看,LinearLayout和FlexBox佈局有很強的概念約束。一個強調線性排布,一個強調盒子模式、伸縮等概念,這些模型在佈局需求和模型概念不匹配時,就不得不借助程式語言進行干預。並且由於佈局系統的隔離,這樣的干預並不容易做,一定程度上影響了佈局的靈活性和表達能力。而配合基於通用程式語言設計的DSL加上AutoLayout的佈局邏輯,可以獲得理論上最強的靈活性。但是這三個佈局系統都在試圖解決“用宣告式的方式表達佈局邏輯的問題”,基於程式語言的DSL的引入讓佈局計算引擎變得多餘。

Picasso佈局DSL的核心在於:

  1. 基於通用程式語言設計。
  2. 支援錨點概念(如上圖)。

使用錨點概念可以簡單清晰的設定非同一個座標軸方向的兩個錨點“錨定”好的檢視位置。同時錨點可以提供描述“相對”位置關係語義支援。事實上,針對佈局的需求更符合人類思維的描述是類似於“B位於A的右邊,間距10,頂對齊”,而不應該是“A和B在一個水平佈局容器中……”。錨點概念通過極簡的實現消除了需求描述和檢視系統底層實現之間的語義差距。

下面舉幾個典型的例子說明錨點的用法:

1 居中對齊:

    view.centerX = bgView.width / 2
    view.centerY = bgView.height /2

2 右對齊:

    view.right = bgView.width - 10
    view.centerY = bgView.height / 2

3 相對排列:

    viewB.top = viewA.top
    viewB.left = viewA.right + 10

4 “花式”佈局:

    viewB.top = viewA.centerY
    viewB.left = viewA.centerX

Picasso錨點佈局邏輯具有理論上最為靈活的的表達能力,可以做到“所想即所得”的表達佈局需求。但是有些時候我們會發現在特定的場景下這樣的表達能力是“過剩的”。類似於下圖的佈局需求,需要水平排布4個檢視元素、間距10、頂對齊;可能會有如下的錨點佈局邏輯程式碼:

    v1.top = 10
    v1.left = 10
    v2.top = v1.top
    v3.top = v2.top
    v4.top = v3.top
    v2.left = v1.right + 10
    v3.left = v2.right + 10
    v4.left = v3.right + 10

顯然這樣的程式碼不是特別理想,其中有較多可抽象的重複的邏輯,針對這樣的需求場景,Picasso提供了hlayout佈局函式,完美的解決了水平排布的問題:

    hlayout([v1, v2, v3, v4],
           { top: 10, left: 10, divideSpace: 10 })

有心人可以發現,這和Android平臺經典的LinearLayout如出一轍。對應hlayout函式的還有vlayout,這一對幾乎完整實現Android LinearLayout語義的兄弟函式,實現邏輯不足300行,這裡強調的重點其實不在於兩個layout函式,而是Picasso佈局DSL無限制的抽象表達能力。如果業務場景中需要類似於Flexbox或其他的概念模型,業務應用方都可以按需快速的做出實現。

在效能方面,Picasso錨點佈局系統避免了“宣告式到命令式”的計算過程,完全無需佈局計算引擎的介入,達成了“需求表達即計算”的效果,具有理論上最佳效能表現。

由此可見,Picasso佈局DSL,無論在效能潛力和表達能力方面都優於以上佈局系統。Picasso佈局DSL的設計是Picasso得以構建高效能四端動態化框架的基石。

同時得益於Picasso佈局DSL的表達能力和擴充套件能力,Picasso在自動化生成佈局程式碼方面也具有得天獨厚的優勢,生成的程式碼更具有可維護性和擴充套件性。伴隨著Picasso的普及,當前前端研發過程中“視覺還原”的過程會成為歷史,前端開發者的經歷也會從“複製”視覺稿的重複勞動中解脫出來。

Picasso高效能渲染

業界對於動態化方案的期待一直是“接近原生效能”,但是Picasso卻做到了等同於原生的渲染效率,在複雜業務場景可以達成超越原生技術基本實踐的效果。就目前Picasso在美團移動團隊實踐來看,同一個頁面使用Picasso技術實現會獲得更好的效能表現。

Picasso實現高效能的基礎是宿主端高效的原生渲染,但實現“青出於藍而勝於藍”的效果卻有些反直覺,在這背後是有理論上的必然性的:

  • Picasso的錨點佈局讓 佈局表達和佈局計算同時發生。避免了冗餘反覆的佈局計算過程。

  • Picasso的佈局理念使 檢視層級扁平。所有的檢視都各自獨立,沒有為了佈局邏輯表達所產生的冗餘層級。

  • Picasso設計支援了 預計算的過程。原本需要在主執行緒進行計算的部分過程可以在後臺執行緒進行。

在常規的原生業務編碼中,很難將這些優化做到最好,因為對比每個小點所帶來的效能提升而言,應用邏輯複雜度的提升是不能接受的。而Picasso渲染引擎,將傳統原生業務邏輯開發所能做的效能優化做到了“統一複用”,實現了一次優化,全線受益的目標。

Picasso在美團內部的應用

Picasso跨平臺高效能動態化框架在集團內部發布後,得到了廣泛關注,集團內部對於客戶端動態化的方向也十分認可,積極的在急需敏捷釋出能力的業務場景展開Picasso應用實踐;經過大概兩年多的內部迭代使用,Picasso的可靠性、效能、業務適應能力受到的集團內部的肯定,Picasso動態化技術得到了廣泛的應用。

通過Picasso的橋接能力,基於Picasso的上層應用程式仍然可以利用集團內部移動技術團隊積累的高質量基礎建設,同時已經形成初步的公司內部大生態,多個部門已經向Picasso生態貢獻了動畫能力、動態模組能力、複用Web容器橋接基建能力、大量業務元件和通用元件。

Picasso團隊除了持續維護Picasso SDK,Picasso持續整合系統、包括基於VSCode的斷點除錯,Liveload等核心開發工具鏈,還為集團提供了統一的分發系統,為集團內部大前端團隊開展Picasso動態化實踐奠定了堅實的基礎。

到發稿時,集團內部Picasso應用領先的BG已經實現Picasso動態化技術覆蓋80%以上的業務開發,相信經過更長時間的孵化,Picasso會成為美團移動開發技術的“神兵利器”,助力公司技術團隊實現高速發展。

列舉Picasso在美團的部分應用案例:

Picasso開啟大前端未來

Picasso在實踐客戶端動態化的方向取得了成功,解決了傳統客戶端“靜態”研發模式導致的種種痛點。總結下來:

  1. 如果想要 敏捷釋出,使用Picasso。
  2. 如果想要 高交付質量,使用Picasso。
  3. 如果想要 優秀使用者體驗,使用Picasso。
  4. 如果想要 高效能表現,使用Picasso。
  5. 如果想要 自動化生成佈局程式碼,使用Picasso。
  6. 如果想要 高效生產力,使用Picasso。

至此Picasso並沒有停止持續創新的腳步,目前Picasso在Web端和微信小程式端的適配工作已經有了突破性進展,正如Picasso在移動端取得的成就一樣,Picasso會在完成四端統一(Android、iOS、Web、小程式)的同時,構建出更快、更強的大前端實踐。

業界對大前端融合的未來有很多想象和憧憬,Picasso動態化實踐已經開啟大前端未來的一種新的可能。

Picasso暫時還未開源,如對Picasso有興趣,歡迎加入大眾點評的大家庭。

作者簡介

曉燕 Picasso核心SDK團隊負責人,八年移動應用開發經驗,2012年加入大眾點評。Picasso 核心SDK團隊致力於探索更好的客戶端動態化實踐方案,貢獻和維護高效能高可靠性的Picasso SDK,同時推進Picasso的應用和大生態的引導和建設。

大為 Picasso專案負責人,點評平臺移動技術負責人,點評平臺在持續交付點評平臺性產品的同時,持續輸出支撐集團移動技術的框架和方案;點評平臺移動技術團隊同時也是廣義的Picasso團隊,全面參與建設了Picasso工具鏈,Picasso持續整合系統,Picasso分發系統,Picasso核心UI元件,點評平臺會持續助力集團移動端業務的動態化演進。

相關文章