攜程Taro多端化探索與實踐
作者簡介
Frank,攜程前端研發(fā),專注前端性能優(yōu)化、一碼多端、工程化建設(shè)等領(lǐng)域。
一、業(yè)務(wù)背景
隨著移動互聯(lián)網(wǎng)和智能設(shè)備的普及,前端開發(fā)人員需要采用多端同構(gòu)技術(shù)來適配不同的終端(小程序、App和Web)。這些終端之間存在著明顯的差異,包括瀏覽器引擎、操作系統(tǒng)、交互方式以及代碼語言等方面。
這些差異給前端開發(fā)人員帶來了不少挑戰(zhàn)。一方面,不同終端采用不同的瀏覽器引擎和操作系統(tǒng),導(dǎo)致頁面渲染和交互行為的表現(xiàn)各不相同。另一方面,不同終端所使用的代碼語言和開發(fā)工具也存在差異,需要開發(fā)人員具備不同的技術(shù)背景和知識,才能編寫多份代碼來適配不同的終端。這樣做不僅增加了研發(fā)人員的開發(fā)工作量和代碼維護的難度,還可能導(dǎo)致用戶在不同設(shè)備上遇到不一致的用戶體驗,影響產(chǎn)品的質(zhì)量和用戶滿意度。
為了解決這些問題,多端同構(gòu)技術(shù)應(yīng)運而生。通過多端同構(gòu)技術(shù),旅游前端和公共團隊合作多端探索與實踐,根據(jù)不同終端的特性進行靈活的適配和定制。這樣可以減少開發(fā)成本和維護難度,提高開發(fā)效率和代碼的可復(fù)用性。同時,多端同構(gòu)技術(shù)還能提供一致的用戶體驗,無論用戶使用哪種設(shè)備訪問應(yīng)用程序,都能獲得相似的界面和功能。
行業(yè)現(xiàn)狀
         
          
    
三端同構(gòu)

二、多端同構(gòu)技術(shù)選型
在進行多端同構(gòu)技術(shù)選型時,我們需要綜合考慮跨端能力、成本、性能、代碼語言通用性以及現(xiàn)有技術(shù)的支持度。這將有助于我們選擇最適合的技術(shù)方案,以下是對當前前端主流跨端技術(shù)的分析:
Hybrid  | React Native  | Flutter  | Weex  | Taro  | |
跨端能力  | ★★★★  | ★★  | ★★★  | ★★★  | ★★★★  | 
成本  | ★★★★  | ★★  | ★★  | ★★  | ★★★  | 
性能  | ★  | ★★★  | ★★★★  | ★★★  | ★★★  | 
代碼語言通用性  | ★★★★  | ★★★★  | ★★  | ★★★  | ★★★★  | 
攜程支持度  | ★★★  | ★★★★  | ★★★★  | ★  | ★★★★  | 
Hybrid:使用JavaScript語言,支持快速構(gòu)建多端應(yīng)用。由于依賴于Webview容器來運行,所以其用戶體驗和性能受到一定的限制的。這種限制會導(dǎo)致應(yīng)用的響應(yīng)速度變慢,頁面加載時間變長等問題。適用于三端業(yè)務(wù)述求比較高,研發(fā)成本又比較低,性能要求不高場景,比如營銷廣告頁。
React Native:使用JavaScript語言開發(fā)的React的組件,支持構(gòu)建App、Web,不支持原生小程序。App上有接近原生應(yīng)用的性能和用戶體驗。適用于對小程序性能要求不高的場景。
Flutter:使用Dart語言和自帶的渲染引擎,支持范圍同ReactNative。在渲染速度和用戶體驗方面表現(xiàn)比ReactNative更加出色。由于ios平臺規(guī)則限制,目前對于熱更新支持并不友好。適用于對App性能要求較高,小程序性能要求不高的場景。
Weex:使用JavaScript語言開發(fā)的Vue的組件,支持范圍與性能同ReactNative,社區(qū)活躍度不如ReactNative。
Taro:開放式跨端跨框架解決方案,它提供了一套統(tǒng)一的開發(fā)語法和組件規(guī)范,使開發(fā)人員能夠使用一套代碼來開發(fā)適配不同平臺的原生應(yīng)用程序。適用于對于三端述求高,性能要求也高的場景。由于設(shè)計之初是面向小程序的,所以規(guī)范上對ReactNative研發(fā)來說并不友好。
考慮到我們業(yè)務(wù)對于多端和性能的要求都很高,結(jié)合現(xiàn)有團隊技術(shù)儲備能力,所以選擇Taro多端同構(gòu)技術(shù)方案。在本文中,我們會重點講述旅游事業(yè)部門票活動前端團隊和公共無線技術(shù)團隊合作將Taro技術(shù)棧與現(xiàn)有技術(shù)進行融合后,遇到的問題以及相應(yīng)的解決方案。
三、Taro如何與現(xiàn)有技術(shù)融合
Taro提供的多端同構(gòu)技術(shù),在不需要考慮與現(xiàn)有技術(shù)棧的結(jié)合的前提下,是可以直接使用的。針對本身已有一套技術(shù)方案情況,就需要考慮如何將Taro與現(xiàn)有的App或Web技術(shù)進行融合。
Taro跨端方案是基于靜態(tài)編譯的解決方案,最終生成的是將源代碼編譯為目標代碼并打包成可執(zhí)行的文件。該文件既不能直接集成到業(yè)務(wù)方(攜程)RN、Web的框架中,也不能直接調(diào)用攜程提供的業(yè)務(wù)組件,如城市、日歷、支付等。因此,開發(fā)者需要對Taro進行適配后,才能解決與現(xiàn)有框架融合的問題。

如上圖,Taro的核心原理是在編譯構(gòu)建時通過注入自定義配置,將原本的小程序組件和API替換為適應(yīng)不同平臺的組件和API,從而實現(xiàn)多端能力。這樣一來,業(yè)務(wù)開發(fā)中可以使用相同的代碼來適配不同的終端,消除多端開發(fā)中的差異。
3.1 融合App(與攜程React Native技術(shù)融合)
1)在Taro的配置文件中,注入自定義plugins插件


2)通過Metro打包配置,進行別名替換(原有的taro引用替換成新的RN路徑)

3)抹平Taro的組件和APIs方法
Text組件

頁面跳轉(zhuǎn)API

按照以上步驟,并且結(jié)合ReactNative的腳手架,就可以運行起來。
3.2 融合Web(與攜程NFES技術(shù)融合)
Taro同構(gòu)技術(shù)已在Web端的非SSR和SSR模式。SSR模式是以NextJS框架未基礎(chǔ)的,通過提供編譯插件tarojs-plugin-platform-nextjs來支持。但由于這個編譯插件并不支持基于NextJS技術(shù)擴展的Web框架或其它Web框架,所以需利用Taro腳手架中開放的編譯能力,在構(gòu)建時通過babel插件將APIs和組件庫替換為支持服務(wù)端同構(gòu)的版本,同時生成適配當前框架的目錄及項目配置,使得Taro具備轉(zhuǎn)換為對應(yīng)Web框架的能力,具體參考如下步驟:
1)同RN,注入自定義H5 plugins插件

2)通過Webpack打包配置,進行別名替換

3)抹平Taro的組件和APIs方法
Text組件

頁面跳轉(zhuǎn)APIs

4)根據(jù)自身框架的調(diào)整路由、中間件等項目配置,以下是攜程NFES示例圖

按照以上步驟,并且結(jié)合自身Web的腳手架,就可以運行起來。
四、技術(shù)實踐
在解決好Taro多端框架與現(xiàn)有技術(shù)融合的問題之后,還需要進一步完善組件和API的豐富度,提升應(yīng)用程序的性能,并解決CSS適配的問題,以實現(xiàn)降低開發(fā)成本和提升用戶體驗的目標。
4.1 組件庫與API
1) 組件和API豐富度
Taro多端同構(gòu)技術(shù)的核心方案是通過抹平組件庫和API差異,實現(xiàn)跨端同構(gòu),從而使得性能和用戶體驗與獨立開發(fā)單一端的應(yīng)用程序相一致。然而,這種方法的不足之處在于需要開發(fā)各端的組件庫和API,以與Taro小程序相對齊,這需要較大的初始成本。
Taro多端設(shè)計時已考慮到了降低研發(fā)人員首次投入的成本,所以提供對齊Taro小程序的組件庫和API,共計60多個。經(jīng)過實踐驗證,已滿足大部分常用的業(yè)務(wù)需求。

除了已提供的組件和API外,仍舊需要開發(fā)面向業(yè)務(wù)的擴展組件和API,例如,彈層、折疊、日歷和城市選擇等組件以及支付、登錄等(如上圖)。大部分組件只需要在官方提供組件上做二次封裝,研發(fā)成本不大。
2) 多端組件和API差異性
多端組件和API在不同平臺上可能存在一些差異,無法完全抹平。每個平臺有自己的特性和限制,因此在開發(fā)多端應(yīng)用時,需要對這些差異進行適配和處理。
比如在動畫實現(xiàn)方面就存在不同平臺之間的差異。在ReactNative中,只能使用Animation組件來實現(xiàn)動畫效果,在小程序和Web端是使用CSS樣式來實現(xiàn)動畫效果,為了盡量保持多端一致性,將動畫實現(xiàn)封裝成一個統(tǒng)一的組件,以便在不同平臺上使用。封裝后的動畫組件,在RN端調(diào)用的是Animation組件,在小程序和Web端則使用組件內(nèi)通過Js添加Css樣式來實現(xiàn)動畫。這種方式解決了動畫實現(xiàn)的差異性,使得開發(fā)人員可以通過使用統(tǒng)一的接口來調(diào)用動畫效果,無需過多關(guān)注不同平臺的具體實現(xiàn)細節(jié)。
把以上遇到抹平問題,可以歸納為以下3類情況:
情況說明  | 解決方案  | 例如  | 
A,B端都有此功能但差異不大  | 抹平差異  | input、路由跳轉(zhuǎn)等  | 
A,B端都有此功能但差異很大  | 抹平差異  | 動畫組件封裝成統(tǒng)一API  | 
A端有此功能但B端沒有  | 降級抹平差異或差異抹平  | 差異抹平:各端實現(xiàn)各端,如RN使用Flatlist,其它端使用scrollview 降級抹平:有的顯示,沒有的不顯示,如頭部導(dǎo)航欄不存在小程序中  | 
4.2 CSS適配
CSS的跨端支持性是較弱的,受限于ReactNative的平臺限制,所以支持并不友好。
ReactNative不支持CSS樣式的嵌套。只能將樣式拆分成多個獨立的對象,并通過StyleSheet.flatten方法將它們合并成一個對象,從而實現(xiàn)在一個層級節(jié)點上設(shè)置獨立樣式。目前只能通過差異抹平適配多端方法,犧牲其他端CSS靈活性。
ReactNative不支持CSS中的偽元素選擇器。如::before和::after,因為它沒有DOM元素并且不支持這些選擇器。可以通過添加HTML節(jié)點來適應(yīng)選擇器寫法。
上述的寫法限制了多端開發(fā)的效率,但并不影響產(chǎn)品的功能實現(xiàn)。另外一些樣式等問題,大部分可以使用Babel插件(如rn-style-transformer)來抹平。
平臺默認屬性差異
屬性  | ios-rn  | android-rn  | web  | 小程序  | 
fontSize  | 14  | 16  | 16  | 16  | 
color  | #000  | #777  | #000  | #000  | 
margin  | 0  | 0  | 8  | 0  | 
padding  | 0  | 0  | 1  | 0  | 
平臺屬性支持差異
屬性  | ios-rn  | android-rn  | web  | 小程序  | 
background  | 不支持  | 不支持  | 支持  | 支持  | 
position:fixed  | 不支持  | 不支持  | 支持  | 支持  | 
textIndent:number  | 不支持  | 不支持  | 支持  | 支持  | 
dashed  | 不支持  | 不支持  | 支持  | 支持  | 
4.3 性能
Taro由于采用的是靜態(tài)編譯時生成平臺代碼,所以性能優(yōu)于動態(tài)編譯時生成的方式。在App端性能和原生RN性能相當,但是在Web端會將Dom節(jié)點替換為Web Component,而Web Component的渲染能力相對于原生組件較低。因此,如果在轉(zhuǎn)換過程中,如果存在大量Web Component,會導(dǎo)致頁面渲染的變慢。在電腦型號為MacBook Pro(14英寸,2021年),瀏覽器型號為chrome,瀏覽器版本為113.0.5672.63(正式版本)(arm64)的測試條件下,以taro-view-core(View)組件為例,重復(fù)渲染2000次,總耗時大約在123ms。如果換成div重復(fù)渲染2000次耗時大約在17ms,大概相差7倍左右,實驗截圖如下:
Web Component耗時:

原生div耗時:

從以上實驗可以得出,不要直接使用 Taro 提供的 View 和 Text 等組件,而是在 Web 原生組件上再包一層具備 Taro 功能的組件。
五、 適用場景和成本
5.1 View層同構(gòu)
根據(jù)交互和產(chǎn)品設(shè)計的需要,對于App、H5、小程序交互方式相似度大于70%建議可以采用一套View,差異部分可以用Taro工程提供的文件擴展名方式實現(xiàn)各自的差異部分。

由于 PC 端的交互方式差異較大,因此通常需要編寫兩套View組件,這樣做比較合適。
5.2 多端同構(gòu)適用場景
多端同構(gòu)適用于需要在多個平臺上提供相同功能的應(yīng)用程序,達到提高開發(fā)效率和用戶體驗的目的。
不適用于對性能要求較高以及高度依賴平臺的專屬特性的應(yīng)用程序,比如基于canvas制作的游戲,對于不適用場景且多個平臺都需要支持的話,只能各自實現(xiàn)各自效果。
5.3 多端同構(gòu)的成本
盡管多端同構(gòu)技術(shù)可以減少開發(fā)的成本,但不同平臺之間仍存在樣式和API的差異,需要研發(fā)人員進行適配和補充。實際各端的研發(fā)成本對比可參考下表:
研發(fā)成本  | 多端同構(gòu)后  | 備注  | |
App  | 1  | 0.2  | |
H5  | 1  | 0.2  | |
小程序  | 1  | 1.2  | 先開發(fā)的平臺  | 
PC  | 1  | 0.4  | |
總計  | 4  | 2.2  | 
隨著開發(fā)經(jīng)驗的積累和組件的豐富化,研發(fā)和測試成本也會進一步降低。
學(xué)習(xí)成本:多端同構(gòu)開發(fā)需要研發(fā)人員具備跨端開發(fā)的能力和經(jīng)驗,需要了解各個平臺的特性和差異,同時還需要關(guān)注代碼的性能、可維護性和可擴展性等方面。我們可以通過多種培訓(xùn)和分享來提高他們的能力和技能。
測試成本:在多端同構(gòu)的開發(fā)模式下,如果不慎改錯一端會影響到所有端,所以測試成本會增加。測試范圍更廣,測試時間也會更長,因此測試成本也會相應(yīng)地增加。另外,由于不同平臺之間的差異,測試人員需要具備跨平臺測試的能力,這也會對測試人員的研發(fā)能力提出更高的要求。為了解決這些問題,可以普及 UT(單元測試)和 AT(自動化測試),這可以降低測試成本,提高測試效率。
生產(chǎn)穩(wěn)定性:因為多端同構(gòu)技術(shù)采用的是統(tǒng)一的代碼邏輯和組件封裝,一旦出現(xiàn)問題,多個平臺都會受到影響。因此,在開發(fā)過程中需要進行嚴謹?shù)臏y試和質(zhì)量控制,以確保代碼的穩(wěn)定性和可靠性。
六、總結(jié)與展望
本文介紹的是通過使用Taro實現(xiàn)多端同構(gòu),在跨多平臺業(yè)務(wù)場景中降低研發(fā)成本,提升用戶體驗。通過使用同一開發(fā)語言和代碼框架,實現(xiàn)在不同端上復(fù)用代碼,達到統(tǒng)一業(yè)務(wù)邏輯的目的。
可以預(yù)見在不久的將來,無論是基于業(yè)務(wù)需求還是技術(shù)實踐與創(chuàng)新,都將出現(xiàn)更多的解決方案,使得多端開發(fā)之路變得更加平坦。同時,這套方案將成為公司主推的多端框架。















 
 
 


















 
 
 
 