Picasso:開啟大前端的未來

背景

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

Picasso:開啟大前端的未來

客戶端動態化

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

客戶端“靜態”開發模式

Picasso:開啟大前端的未來

客戶端開發技術與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另闢蹊徑,在實現高性能動態化能力的同時,還以較強的適應能力,以動態頁面、動態模塊甚至是動態視圖的形式融入到業務開發代碼體系中,贏得了許多移動研發團隊的認同。

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

Picasso動態化原理

Picasso:開啟大前端的未來

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

Picasso:開啟大前端的未來

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

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

Picasso佈局DSL

Picasso:開啟大前端的未來

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

  1. Android開發常用的LinearLayout。
  2. 前端及Picasso同類動態化框架使用的FlexBox。
  3. 蘋果公司主推的AutoLayout。

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

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

Picasso:開啟大前端的未來

Picasso佈局DSL的核心在於:

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

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

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

1. 居中對齊:

Picasso:開啟大前端的未來

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

2. 右對齊:

Picasso:開啟大前端的未來

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

3. 相對排列:

Picasso:開啟大前端的未來

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

4. “花式”佈局:

Picasso:開啟大前端的未來

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

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

Picasso:開啟大前端的未來

 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佈局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動態化技術得到了廣泛的應用。

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

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

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

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

Picasso:開啟大前端的未來

Picasso:開啟大前端的未來

Picasso開啟大前端未來

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

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

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

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

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

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

Picasso:開啟大前端的未來


分享到:


相關文章: