淘寶Native研發模式的演進與思考 | DX研發模式
DX全稱DinamicX,目前是在淘寶乃至整個阿里集團內廣泛使用的Native動態化方案,核心優勢是效能和穩定性。過去幾年一直有其他淘寶/集團的外部文章中有涉及到DX,但DX一直沒有對外做過完整介紹,對外界來說這兩個字母頗有些神祕色彩。本系列文章《DX研發模式》我們就將拉下它神祕的面紗,看看過去兩年 DX 在做什麼。
本文主要闡述 DX 的發展歷程以及近兩年的重點建設事項,喜歡看影片和PPT的同學,可以在【阿里巴巴移動技術】公眾號內回覆「DX」,觀看去年末筆者的分享“淘寶Native研發模式的演進”。
《DX研發模式》系列文章如下,歡迎關注:
本文:《淘寶Native研發模式的演進與思考》
作者:周杰(尋弦)
DX的起源與發展
DX是從首頁為解決業務兩端一致性和動態性的問題孵化而來,後經過若干次升級和迭代,逐步完成了從首頁動態化方案——基礎鏈路動態化方案——集團共建動態化方案——集團移動小組標準Native研發模式的多級跳躍。隨著接入的業務和開發者越來越多、使用場景越來越複雜和多樣,技術範疇也從端側SDK延展到動態化技術體系,再到Native研發模式。
淘寶的技術選型
這可能是當前這個星球上最複雜App的淘寶技術選型標準,我們把淘寶所有的業務分為三個大類:核心域、導購域和開放域。不同場景對於效能體驗、穩定性、交付效率都有不同的訴求,這裡沒有“技術銀彈”,只有適合目標場景的最佳方案。
過去兩年我們面臨的挑戰是什麼
作為核心域標準技術選型的DX,過去幾年的挑戰是什麼呢?
首先來看一下大的業務背景:
- 業務競對加劇,集團從航母戰略升級為App矩陣戰略,對交付量和效都有了更高的要求;
- 隨著直播/短影片/AR/3D技術的發展與普及,移動端邁入沉浸式/富互動體驗,Native技術棧的優勢更加明顯;
- 淘寶的購物效率越來越高,使用者訪問時長/頻率降低,大部分購買決策發生在淘外,淘寶逐漸淪為下單/比價工具,而當內容場掌握了大量入口流量和使用者時長後,開始下場自己閉環做電商成交,曾經的引流渠道變成直接競爭對手,淘寶也將面臨“無源之水、無本之木”的困境,所以淘系近年來一直在打造自己的內容/社群,讓更多的消費購前決策發生在淘系。
這三大業務背景深刻地影響著接入DX的每個業務以及潛在的新業務,所以過去兩年,我們的工作主要圍繞研發模式升級和體驗升級來進行。
首先來說研發模式升級,原先主要有兩個問題:
1、DX自身技術體系不完整,在19年之前,DX只能說是一個客戶端動態化方案,包含一個端側SDK和一個元件平臺,但隨著接入的新業務越來越多,DX自身技術體系不完整的瓶頸愈發明顯,大量新業務需要重複建設端側容器、搭建平臺等基礎設施,導致接入成本高、收益低,而各業務自建的容器和平臺,又難以沉澱和複用,進一步加劇了後續技術拉通的難度。
2、研發模式過於單一,隨著沉浸式體驗和富互動體驗的鋪開,很多業務告別了過去重展示輕互動的模式,往中度互動開始進行體驗升級,尤其以微淘拆分出的逛逛和訂閱為代表的類內容場,需要以更沉浸式的瀏覽/互動體驗來吸引使用者更多的停留和內容消費,而我們過去基於搭建的方式並不能很好地對此類場景進行研發支撐。
再來是體驗升級,我們雖然並不能決定具體業務場景的視覺互動和體驗設計,但面向優秀的體驗,我們可以做幾個事情:
- 提供開箱即用的體驗優秀的標準化元件,如日曆/富文字/複雜巢狀容器/Page Indicator等元件,極大降低體驗精細化帶來的適配成本,如Dark Mode/銀髮版字型自動放大適配等;
- 在富媒體/端智慧的快速發展,以及下沉市場中低端裝置的增加的背景下,持續優化DX渲染管線的效能水位,提升廣大業務場景的基礎瀏覽和互動體驗;
- 提供更完善的效能工具,幫助開發者在面對相對“黑盒”的模版效能問題時,可以做到早發現、可排查、可優化。
關於ProCode和LowCode的思考
在我們承接新訂閱和逛逛的新場景時發現,在這種內容型互動類場景,有著豐富的互動、聯動與轉場,DX過去動態邏輯表達力不足和基於模組搭建的LowCode研發模式無法支撐其進行高效研發,核心矛盾是動態邏輯、複雜容器及內部聯動、多人並行開發與模組引用,於是經過一系列的討論和思考後,有了下面這張圖:
基於在新場景下面臨的問題,我們決定把研發模式進行分層,定製性強/動態邏輯要求高的業務場景,用ProCode模式來開發,通過強大專業的DX IDE+Git來進行工程化多人協作開發,可以進行UI和動態邏輯的除錯(事件鏈),而定製性弱/複用性高的業務場景,用LowCode模式來承接,通過視覺化搭建平臺來拖拽生成檢視和佈局,配置相應資料來源和規則。同時,不斷抽象沉澱元件庫/能力庫,使越來越多的互動/功能/佈局可以通過視覺化方式來拖拽生成。
我們暢想的未來是,當業務同學有一個新的業務想法時,可以通過LowCode模式自行搭建與配置,在線上圈選小部分使用者進行灰度驗證,在驗證產品方向正確後,再投入更多的專業技術人員來做進一步的產品定製和升級,來產生更大的業務效果。
ProCode “三駕馬車”
要讓 ProCode 模式成型,必須要解決的是動態邏輯、複雜容器和相應的研發支撐問題,所以就有了ProCode的“三駕馬車”:IDE、列表容器、事件鏈。
IDE
第一是IDE,這裡補充些背景資訊,在做IDE之前,DX有個模版平臺,主要來承載模版的開發/除錯/釋出工作,那我們為什麼要再做一個IDE呢?
首先,嚴格來說,原來DX平臺上的不叫IDE,只能說是Editor,從關係上來看,IDE包含Editor,借用一張VSCode的圖來說明兩者的差異:
其次,原來DX平臺上的Web Editor(Monaco)雖然也支援大部分LSP API,但沒有工程/專案體系、檔案系統、程式碼上下文理解、除錯等能力,且受限於瀏覽器環境,而IDE運行於本地環境,有豐富的擴充套件能力和外掛,可以提供完整的研發生命週期支援。
所以,在ProCode模式下,我們的技術選型基於Katian IDE(相容VSCode API),來得到更多的檢視擴充套件能力,未來還能通過靈活的部署方式(遠端開發、雲端部署),實現更高效/快速的研發與協作。
目前DX IDE已經接入了包括淘寶在內的集團多個重要業務,這些開發者使用IDE後研發效率有了大幅的提升,尤其是多人協作與除錯效率有了量級的提升。關於DX IDE更詳細的介紹,可以閱讀系列文章之《從0到1,IDE如何提升端側研發效率?| DX研發模式》
列表容器
第二是列表容器,過去基於搭建的容器有個特徵,容器/頁面佈局由資料協議來描述,即資料佈局一體,這在簡單頁面結構(如單列表頁面)場景下運轉良好,配合搭建能較快地配置出樓層,通過協議來驅動端側渲染,服務端也不需要過多感知業務結構(預設就是單列表佈局)。但在複雜頁面結構(如多層多Tab巢狀容器),尤其還有複雜互動的情況下,就會讓整個資料結構變得過於複雜,同時也增加資料協議的paylaod,而頁面佈局的變化頻率遠小於業務資料。
在這種場景下,把兩者耦合在一起,明顯是不合適的,於是,出於職責單一和“動靜分離”的原則,我們進行了重新的思考和設計,在模版XML中統一描述佈局(包括容器/頁面佈局),讓資料迴歸純粹的資料結構,與此同時,我們也在DX中內建了新的功能強大的列表容器,寫起來就像下面這樣:
<RecyclerLayout
userId="recycler"
width="match_parent"
height="match_parent"
dataSource="@data{itemList}"
backgroundColor="@triple{@getEngineStorage{backgroundColor}, @getEngineStorage{backgroundColor}, '#ffffff'}"
columnCount="2"
columnGap="4"
isOpenPullToRefresh="True"
refreshPullText="下拉即可重新整理..."
refreshReleaseText="釋放即可重新整理..."
refreshLoadingText="載入中..."
loadMoreFailText="載入失敗"
loadMoreLoadingText="載入中..."
loadMoreNoMoreDataText="到底了"
onPullToRefresh="@dxEventHandler{'refreshTest'}"
onEndReached="@dxEventHandler{'loadMoreTest'}"
>
<Template
if="@subdata{span}"
sticky="True"
colspan="2"
name="aa"
>
<TextView
width="match_parent"
height="100"
text="@data{text}"
textSize="15"
backgroundColor="#FFFF55"
borderColor="#FF9911"
borderWidth="2"
/>
</Template>
<Template
if="@subdata{recyclerInsertItems}"
name="recycler_sub_template1"
version="2"
/>
</RecyclerLayout>
目前列表容器已覆蓋了多個淘寶和集團內重要業務場景,支援了巢狀容器/聯動框架/動態Template/Slot等能力,下一年我們也會推廣到更多的業務。
事件鏈
第三是事件鏈,過去DX只支援UI的動態化,有限的邏輯控制只能通過表示式來實現,其他的邏輯變更都依賴發版,而隨著業務對釋出上線的時效要求越來越高,邏輯動態化的訴求也愈發強烈。於是,面對這個訴求,我們經過反覆的討論和思考,綜合考慮了蘋果合規、效能、穩定性、開發效率,提供了事件鏈的方案。
在事件鏈方案中,開發者在XML對應的eventchain.json中使用原子能力和表示式進行邏輯組裝,在研發期IDE提供了事件鏈JSON的智慧感知能力(包括補全/提示/跳轉/格式化/摺疊/高亮等),可以通過事件鏈回放功能,來圖形化顯示事件鏈執行的流程以及每個原子能力的出入參和上下文,來便捷問題的排查。開發完成後,在編譯階段,DX編譯服務會把該JSON編譯成二進位制,與模版二進位制一起下發,確保效能和一致性,在端側有事件鏈引擎來負責二進位制的解析,以及原子能力的排程。
想了解列表容器和事件鏈更多的技術細節,可以期待和閱讀本週四(5.26)上線的系列文章 列表容器&事件鏈如何助力業務快速迭代 | DX研發模式。
關於效能優化的思考和實踐
過去兩年,DX的能力越來越強大,功能越來越豐富(動畫動態化、事件鏈、複雜巢狀容器、直播/影片元件、3D元件等),那DX一直以來的效能優勢,會不會有所影響或下降?我們又是如何在不斷加入新功能的同時,做到效能不退反升呢?面對越來越複雜的模版,如何幫助開發者在面臨效能問題時,有排查和優化的抓手,而不是一無所措呢?
這就要說下DX的渲染管線,如果說Flutter是接管整個系統渲染的革命派,那DX就是基於原生系統渲染的改良派。DX的主要設計思路是基於Platform First來改良系統原生渲染管線/機制中的效能瓶頸和問題,並做到兩端統一。
從DX管線各階段的耗時分佈來看,主要大頭在load和render,所以我們主要通過非同步化管線來解決load的耗時問題,通過非同步繪製和高效能元件來解決render的耗時問題,通過計算資源管控來儘量保障資源的合理分配。
非同步化管線和非同步繪製,主要是讓更多工作能夠在子執行緒執行,或者並行排程,降低主執行緒的負擔,合理利用多核計算資源,在DX列表容器中,我們內建了該能力,可以做到開箱即用,而在業務容器中,需要業務方按照我們建議的時機/業務認為合適的時機來呼叫相應API,來獲得非同步化的排程。
高效能元件方面,我們主要優化了圖片元件和自研了富文字元件,尤其是富文字元件,我們基於系統TextKit/TextLayout實現了自測自繪,提供了TextSpan/ImageSpan/展開收起等能力,相比原生元件,記憶體降低(iOS 70% Android 8%),效能提升(iOS 20% Android 10%)。
計算資源管控方面,我們主要設計和實現了離屏計算資源管控框架,用來實現影片/直播/動圖的播控問題,且提供了規則配置能力,在多影片情況下,iOS CPU佔用率降低66%/Android降低25%,目前在淘寶的一些重要資訊流場景已上線。
效能工具方面,過去我們主要是在執行時進行各種底層優化和編譯期的效能預警提示,在遇到模版效能問題時,通常需要業務方和DX同學分別打Log來看時間的消耗和定位問題的所在,雙方都耗時耗力。會出現這種情況,一部分原因是DX與Native的結合度較高,一次渲染過程中有大量的DX內部程式碼和業務方自定義程式碼交織在一起,導致無法快速精準定位問題所在;另一部分原因是DX的渲染過程對業務方來說相對黑盒,業務方也沒有進行排查和優化的有效抓手。
為了擺脫這種場景,我們要讓整個模版渲染過程在開發階段進行一定的白盒化,以視覺化圖形方式展現模版各階段的渲染耗時及其歸屬(DX內部還是業務方自定義部分,具體到是哪個Widget的什麼階段/DataParser/EventHandler),同時通過不斷累積的常見效能問題,進行模版自動分析並提供一定的優化建議。
關於效能優化的思考和實踐,可以閱讀系列文章之 如何持續突破效能表現?DX 效能優化策略詳解
技術大圖
總結一下,這是目前DX技術體系的大圖,研發支撐層,我們通過IDE和平臺來滿足ProCode和LowCode兩種生產模式的訴求,核心執行時層,我們不斷增強容器/元件/佈局等檢視能力的同時,引入一定的動態邏輯能力,通過共建不斷沉澱原子能力庫,業務框架層,我們也與淘寶內團隊合作,把複雜狀態管理、流程編排等能力引入DX技術生態中,業務可按需接入。
未來展望
從技術演進上,我們認為DX的下一階段,要實現三化:
- 標準化,目前DX的DSL偏向私有標準,開發門檻較高,不利於擴大開發者群體,接下來我們要向客戶端行業標準靠齊,吸引更多的開發者;
- 現代化,目前DX通過命令式來描述UI,而行業已經向宣告式邁進,從技術演進路線上,我們也要擁抱宣告式,進一步提升開發體驗和效率,此外,研發支撐方面,我們這個財年從0到1打造了DX IDE,在本地進行安裝和執行,已經能較大程度提升複雜頁面/模版的研發效率,但我們不會停下研發提效的腳步,接下來還要嘗試通過雲端部署的方式,達到免安裝/開箱即用/工作空間共享等,進一步提升研發和協作效率;
- 一體化,目前我們已經通過DX IDE實現了部分的工程一體化,未來為了進一步提升前後端協作效率,也為了把Serverless打造成客戶端的基礎能力之一,我們要實現端雲一體,在一個整合研發環境中,以同一個技術棧,同時開發端側和雲側程式碼,簡化端雲遠端排程開發成本,釋出期通過編譯技術部署到不同的目標,提升前後端協作效率和端側技術方案自主性。
當然要實現這些,還有大量的技術挑戰在前方等待著我們,歡迎有興趣的同學和我們進行技術交流,或者加入我們(聯絡郵箱:[email protected]),大家攜手一起創造客戶端的未來!
關注【阿里巴巴移動技術】,阿里前沿移動乾貨&實踐給你思考!
- 文字佈局效能提升 60%,Inline Text 技術原理與實現 | Cube 技術解讀
- Android Target 31 升級全攻略 —— 記阿里首個超級 App 的坎坷升級之路
- 系統困境與軟體複雜度,為什麼我們的系統會如此複雜
- 系統困境與軟體複雜度,為什麼我們的系統會如此複雜
- Cube 技術解讀 | Cube 渲染設計的前世今生
- 淘寶Native研發模式的演進與思考 | DX研發模式
- 大量模組殼工程本地如何快速編譯?優酷 iOS 工程外掛化實踐
- 大量模組殼工程本地如何快速編譯?優酷 iOS 工程外掛化實踐
- 從0到1,IDE如何提升端側研發效率?| DX研發模式
- 優酷移動端彈幕穿人架構設計與工程實戰總結
- 2022 支付寶五福 |“聯機版”打年獸背後的網路技術 RTMS
- Flutter 圖片庫重磅開源!
- 如何持續突破效能表現?DX 效能優化策略詳解
- 淘寶Native研發模式的演進與思考 | DX研發模式
- 前車之鑑:聊聊釘釘 Flutter 落地桌面端踩過的“坑” | Dutter
- 釘釘 Flutter 跨四端方案設計與技術實踐 | Dutter
- 前車之鑑:聊聊釘釘 Flutter 落地桌面端踩過的“坑” | Dutter
- Dutter | 前車之鑑:聊聊釘釘 Flutter 落地桌面端踩過的“坑”
- Dutter | 釘釘 Flutter 跨四端方案設計與技術實踐
- Swift 首次除錯斷點慢的問題解法 | 優酷 Swift 實踐