天天看點

Taro 在多端浪潮下的選擇與挑戰

作者|朱天健

編輯|賈亞甯

本文由 InfoQ 整理自京東零售平台業務中心進階前端工程師朱天健在 GMTC 全球大前端技術大會(深圳站)2021 的分享《Taro 在多端浪潮下的選擇與挑戰》。

多端研發對于當今時代的前端開發來說是個繞不過去的話題,為了解決這些問題,各大公司的開源項目推出的開源架構不在少數,而 Taro 從 2018 年開源至今已經三年有餘,在 GitHub 上收獲了超過 3W 的 Starred,在開源後幫助很多團隊和開發者的同時,我們也通過與社群内萬餘活躍使用者的交流和回報摸索前進的方向,與諸多開發者一起共建社群,和 Taro 一起成長。

我們需要一個怎樣的多端解決方案

小程式生态共榮

我們到底需要一個怎樣的多端解決方案呢?以 Taro 的視角來說,我們基礎的前提是希望多端不會成為開發者的障礙,特别是在小程式生态整體上呈現欣欣向榮之勢時,我們期待整個生态都可以繼續成長,與開發者們互相成就。

近幾年來,每隔一段時間就會有很多新的小程式平台出現,帶來了更多流量管道的同時,也給開發者創造了很多難題。

小程式平台

産品同學可以很輕易地喊出“我全都要!”,那麼我們作為開發可以嗎?不論是 Web 、React Native 端,還是各類小程式平台,在開發過程中都勢必會牽扯很大的精力。特别是平台方很多時候也沒有足夠的時間和精力照顧到所有開發者的開發體驗,而同樣對于很多跨端架構的開發者來說,适配一個全新的平台也勢必不是一件容易的事情。

跨平台開發是小程式生态持續擴張的重要力量,同時也使小程式成為網際網路生态快速拓展的核心之一。這就是為什麼我們期待中的小程式生态需要大家共同建設,每一個新成員的加入,帶來的都不僅僅是流量,更是新鮮的活力,這些都會促進整個生态的繁榮。

開發性能與體驗

但是,這裡就不得不提到但是了!!!代價又是什麼呢?

面對多個平台同步開發的過程中,我們往往會遇到很多問題,比如:為了同步多端能力,我們往往很難快速響應業務需求;如果采用原生開發,每增加一個平台,研發成本都是指數級增長;而開發完成并不意味着任務結束了,維護這些多端同構又具有差異化的代碼的困難程度可想而知。

是以對于開發者來說需要的無非是多端一體化的開發體驗;希望架構在開發維護舒适的同時,還可以擁有卓越的性能。插件化同樣是十分重要的能力,對于很多項目不需要的能力完全可以自主選擇;而對于更多社群的開發者群體來說,如果有特殊的需求,可以通過定制化的插件去實作,而不需要等待官方響應。

面向開放、開源社群、開發者

本質上我們需要面向開發、面向開源社群中的各個團隊以及其中諸多開發者開放架構的能力。

支援更多架構

我們希望可以讓開發者自由地選擇自己喜歡的架構,不論你是喜歡 React、Vue 還是更多其他的解決方案,都可以不受限制地去使用這樣一個多端解決方案去實作自己的創意,這才是開源的精神,也是我們做開源項目的目的。

當然這也就有了 Taro 向社群内所有開發者提供的開放式跨端跨架構解決方案。

高拓展性的開放式架構

沒有什麼是一蹴而就的,對于 Taro 團隊來說,我們面臨的很多問題也是一樣的。雖然剛剛我們提到了很多,但這些内容也是我們一組一個腳印慢慢實作地。而在最早期的時候,Taro 還沒有這麼開放,它隻支援 React Like 的方式去寫小程式,而且還是一個重編譯時的架構。

Taro 在多端浪潮下的選擇與挑戰

Taro 架構

就像這個架構圖顯示的一樣,我們通過 AST 解析開發者的 React Like 代碼,轉換成對應端的小程式代碼,通過适配層就可以完成所有小程式的适配。雖然一句話就可以講完我們所有的工作,但是其中的困難很多都難以想象,我們發現維護架構的成本逐漸超出了我們可以接受的極限,是以我們選擇向前再邁出一大步。

插件化架構

不得不說,插件化架構給我們了很大幫助,我們将所有可以拆分出來的東西悉數拆分,幾乎所有的能力都是通過插件化的方式提供,最終也就形成了 Taro 3.x 的架構。

在 Taro 3.x 對整體架構調整之後,大大降低了适配新架構的成本,通過對齊元件和生命周期我們就可以在 Taro 的生态中引入一個新的架構。

Taro 在多端浪潮下的選擇與挑戰

Taro 3.x 架構

當然在這個架構中 Web 、React Native 和小程式端的實作略有不同。在小程式中,我們需要注入 DOM、BOM 并提供對應架構的渲染器,最終通過 Webpack 打包給開發者使用;Web 端則是通過 WebComponent 提供了标準化的元件,同時結合标準的路由體系模拟了所有的 API 提供給開發者;React Native 中也是同樣的邏輯,通過 Metro 将标準化的元件和 API 打包給開發者使用。

Taro 在多端浪潮下的選擇與挑戰

端平台插件

插件化架構幫助我們引入了一個新概念——端平台插件,它幫助我們将每一個端的能力拆分開,插件通過提供編譯時的模闆、元件、編譯配置,加上運作時所需的元件、API 和渲染器,将它們分别注入 Taro CLI 和 Runtime 中對應的生命周期,Taro 就能夠轉譯成對應端的代碼。

以微信小程式插件 @tarojs/plugin-platform-weapp 為例,我們通常會按照如下方式組織項目檔案:

通過繼承基類 TaroPlatformBase 實作端平台的編譯,然後在插件入口函數中調用上述自定義平台類的編譯接口:

runtime.ts 是我們運作時的入口檔案, Webpack 編譯時會把它注入到 app.js 中進行引用。

使用 mergeReconciler 函數把自定義的 hostConfig 合并到全局 Reconciler 中;

使用 mergeInternalComponents 函數把自定義元件資訊 components.ts 合并到全局 internalComponents 元件資訊對象中。

參考 @tarojs/plugin-platform-weapp 插件我們可以快速注冊一個其他端的小程式插件,橫向拓展自定義所需的元件、API、渲染器和運作時。當然也可以此為基礎縱向拓展一個平台插件,這樣可以快速完成相似的小程式平台插件開發。

當然整個插件架構的設計并不僅僅是用于建構端平台插件,各類插件都能很好地完善 Taro 生态,提供更好的開發體驗,社群内很多開發團隊或者個人都提供了非常有意思的插件用于各種研發場景,歡迎大家體驗。

跨架構适配

想要适配架構對于現在的 Taro 來說,并非是一件非常困難的事情,因為 Taro 提供了自己模拟的浏覽器環境。

Taro 在多端浪潮下的選擇與挑戰

Browser Object Model

模拟浏覽器環境

作為浏覽器環境的基礎,BOM 和 DOM 相關的 API 是必不可少的,這也是供各類前端架構在小程式中運作的根本。

Taro 在多端浪潮下的選擇與挑戰

Taro RuntimeTaro

通過模拟這些 API 建構了自己的運作時環境,将所有的事件和節點方法在小程式環境中以對齊 Web 标準的形式呈現。

以基礎的 click 事件為例,當小程式中 tpl_text 節點觸發事件時,架構會通過 Taro DOM Tree 提供的 getElementById 方法找到 text 上的 onClick 方法找到相應的事件并觸發。

同樣冒泡機制也是事件中重要的組成部分,是以在父級節點 tpl_view 上的 onClick 方法同樣會被觸發,這時就需要通過調用 stopPropagation 方法來阻止事件的傳播。

架構相容

在完成浏覽器環境的建構之後,相容各類架構相對就容易很多,通過 Taro 提供的标準事件将架構的生命周期和小程式關聯到一起,就能夠讓開發者在使用時有更順滑的體驗。

首先要做的就是挂載入口,将建構好的 DOM 樹在小程式觸發 onLaunch 事件時挂載上去,當然每個架構有自己的寫法,比如 React 中是 render Vue 中是 $monut 方法。

緊接着我們需要挂載頁面,在頁面觸發 onLoad 時為頁面注入 ref 等資訊,并将頁面渲染呈現。而每個頁面都會有屬于自己的 pageId,這也使得我們可以将所有的生命周期和每個頁面一一對應,在合适的時機觸它們。

當生命周期對齊,頁面隻要渲染出來就可以了,當然這裡每個架構會有些不同。以 React 為例,ReactDOM 作為渲染器,功能非常豐富,但包體很大而且并非所有都在小程式中需要用到,選擇使用 react-reconciler 自定義渲染器精簡是個很容易做出的決斷,加上 hostConfig 注入對應的依賴, taro-react 就完成了。

Taro 在多端浪潮下的選擇與挑戰

适配 React 自定義渲染器

在運作時中通過 createReactPage 就可以建立 Taro DOM Tree 并通過 setData 和模闆互動資料完成渲染。

Taro 在多端浪潮下的選擇與挑戰

圖檔适配 React 渲染流程

在 Taro 中使用 Vue 也是一樣的,通過調用 createVuePage 建立 DOM Tree 之後就可以實作打通整個流程。

Taro 在多端浪潮下的選擇與挑戰

适配 Vue 渲染流程

當然大家如果使用 Taro 支援新架構時,可能會遇到一些問題,比方說 DOM/BOM 相關的 API 缺失或者功能錯誤等等,可以通過 issue 回報,我們會動态拓展。

跨端适配

對于 Taro 來說端有很多,小程式端、React Native 端、Web 端、快應用端,其中很多都是社群幫助完成适配的。在這裡我們以小程式端為例,Taro DOM Tree 在渲染的過程中根據不同的小程式平台其實是會有所不同的,但都是基于 template 元件提供的渲染方法。

渲染方案 3-1

通過模闆的一一對應,我們就能完成所有元件的渲染,但不同平台的模闆功能是差異化的,有的支援遞歸,而有的并不支援,這也就分成了兩種不同的小程式類别。比方說阿裡、頭條、百度的小程式都支援遞歸,我們可以讓模闆自我調用來避免重複。

渲染方案 3-2

而微信、京東、QQ 小程式不支援,我們則會建立新的模闆。不支援遞歸的模闆模式當然有可能會存在一些問題,比方說模闆檔案過大,但我們可以通過設定 baseLevel 配置合理優化遞歸層級數;同樣因為自定義元件樣式會有影響,避免嵌套也是一個優化的方案。

渲染方案 3-3

Taro 在多端浪潮下的選擇與挑戰

小程式

不知道你是否嘗試使用 Taro 編譯快手、芒果、飛書,甚至是支付寶 IOT 小程式呢?這些新增的平台有些是官方的小程式平台提供,也有很多其他公司的團隊或者個人開發者根據自身的業務需求開發提供的,當然也期待可以在社群中看到更多大家編寫的 Taro 平台插件。

小程式和 H5 的生态融合

說起小程式和 H5 的生态融合,不知道大家會想到什麼呢?可能也會困惑什麼是生态融合?Taro 為什麼要做生态融合?又是怎麼做到生态之間的融合呢?

什麼是生态融合?

Taro 已經支援了這麼多小程式平台,同時也支援了 H5 端,那麼是不是大家都使用了 Taro 架構,小程式端和 H5 的生态就可以融合起來呢?顯然不會是。

在各個不同的小程式生态之中沉澱了大量專屬的小程式插件,如果開發者想要使用 Taro 的同時直接利用這些專屬的原生小程式能力可以麼?這顯然不會有任何問題能形成阻礙。

那麼原生小程式能不能通過 Taro 轉換成 H5 應用呢?通過 Taro 的 convert 指令你就可以完成原生到 Taro 項目的過程,Taro 可以幫助你轉換到任何平台去使用。

那麼這就夠了麼?我有一個原生的項目可不可以使用 Taro 編寫的元件呢?有同學可能會說 Taro 可以編譯小程式插件的,你導出插件就可以在原生應用使用 Taro 。但實際上 Taro 同時還提供了 blended 指令,可以将 Taro 項目編譯到指定平台,供原生小程式或者其他端的應用內建使用。

除此之外還有嗎?Taro 可不可以直接在小程式使用 web 元件呢?

使用 HTML 标簽

仔細思考一下,這件事情完全是可以的!是以我們新增了一個插件 @tarojs/plugin-html 來完成這件事情。

實作這個插件籠統地說,我們的任務主要劃分為三個方向,分别将标簽名、屬性、元件映射就可以了,當然實際上還是會遇到很多問題,但這是有價值的,特别是它在社群内有很高的呼聲。最重要的原因就是我們可以通過這個插件直接在小程式中使用 web 端的各種工具,特别是一些元件庫,我們可以直接在 Taro 中使用而不需要特别考慮跨端的問題。

比如 Ant Design、 Vant 以及 WeUI 我們都提供了 demo 給到社群可以直接使用,這将進一步打通 Web 端和小程式端的生态壁壘,同樣很多老項目都可以直接在小程式端直接運作,也會是一個很大的便利。

圖檔小程式使用 web 端生态

當然這并非毫無限制,比方說 DOM API 會有一些差異:

小程式部分 API 不支援同步調用

小程式部分元件 API 需要通過 Context 調用

同樣一些特殊的用法,包括部分标簽節點,在使用時也存在一定的差異:

不支援在 DOM Tree 之外插入節點(React 的 Portal,Vue3 的 Teleport 都是不支援的)

ReactDOM 功能精簡(Taro 使用 react-reconciler 自定義調試器)

小程式不支援部分樣式或 CSS 選擇器(預設寬高并非原圖寬高)

小程式不支援 svg

更多限制細節可以參考官網上的相關文檔。

鴻蒙帶來的機遇和挑戰

Taro 也能支援鴻蒙嗎?這是我在很多社群的交流群中聽到最多的一句話,但其實 Taro 支援鴻蒙是可行性非常高的,畢竟 OpenHarmony 的 JS UI 文法和小程式的相似度很高。是以其實早在鴻蒙第一次曝光時雙方的團隊就有過很多深入地交流,并探讨過相關的可行性,當然一直到近期我們才有足夠的人力去完成鴻蒙平台的适配。

Taro 和華為以及開放原子基金會都多有合作,但是總結下來就是 Taro 即将加入 OpenHarmony 并成立 CrossPlatformUI Sig,為鴻蒙提供跨端能力的支援。

Taro 在多端浪潮下的選擇與挑戰

對于 Taro 來說,我們同樣可以通過插件的形式适配鴻蒙,将它作為一個平台橫向拓展就可以完成鴻蒙的接入。

當然為了抹平鴻蒙和其他平台的差異,我們需要針對處理的問題還有不少,比方說支援 React&Vue 文法,支援标準的元件和 API 等等,支援文法通過編寫架構的運作時就可以實作,而元件和 API 則需要通過 OH 提供的能力來實作。

最終就可以看到我們寫的代碼可通過 webpack 打包成應用,在前端架構層通過 Taro 提供的運作時與 UI 視圖互動資料和事件,加上 OH 提供的基礎能力就可以為鴻蒙端适配渲染。

Taro 在多端浪潮下的選擇與挑戰

Taro 适配 OH 的渲染流程

Taro for Harmony 相關的能力将會作為 v3.5 版本的特性釋出,目前 canary 版本已經釋出,歡迎大家踴躍嘗試,我們也會和社群諸多開發者們一同持續完善相關的能力,并提供支援。

總結和展望

最後的最後,關于 Taro 還在做的事情其實還有很多,我們在這裡簡單地總結展望一下。

Taro for Harmony

首先是就 Taro for Harmony,剛剛其實也有提到,我們很快會釋出正式版本,目前正在邀請社群的同學進行内測當中,正式版本釋出時間,我們預計會在 2022 年 3 月份,大家感興趣可以關注,當然也可以通過小助手加入 Taro 的鴻蒙交流群,擷取更多的資訊。

跨平台測試

跨平台測試一直以來都備受社群開發者們的關注,我們其實在内部已經有兩套方案持續疊代當中,隻是由于很多原因一直沒有開源出來給大家使用。

Taro 在多端浪潮下的選擇與挑戰

沙箱測試

測試沙箱作為一套自研的方案,可以完全适配全平台的小程式和 Web 端的邏輯測試,通過模拟小程式的 DOM 結構、生命周期和 API 來輔助開發者完成小程式相關的能力測試;在 Web 端則是通過解析生成代碼的 AST 擷取應用和 Taro 執行個體,結合 Jsdom 模拟實際的浏覽器環境,達成和小程式一緻的測試體驗。

自動化測試

另一個方案 TIga 則相對更真實,通過 puppeteer 和小程式官方提供的接口在浏覽器環境或者小程式官方平台提供的測試環境中完成 UI 測試,目前支援了 Web 端和微信小程式,在内部項目的使用中也廣受好評。兩個方案各有側重,希望有一天能夠開源,與社群的開發者見面。

Cloud IDE

Cloud IDE,也就是 Tide 項目,也傾注了我們團隊很多成員的心血,通過内置的 Taro 研發流程,很好地解決了在小程式開發過程中的諸多癢點,比方說模闆、插件管理,多端配置差異,版本管理等等工程化的問題。

Taro 在多端浪潮下的選擇與挑戰

在大型小程式項目中産品、設計、研發和測試之間的團隊協同;同時通過内置的小程式模拟器,避免了調試中視窗反複切換開發者工具模拟器;小程式測試上線流程、線上環境監控……這些目前在内部使用的反響都不錯,很好地幫助我們解決了很多團隊内的問題。

文末回答兩個大家關心的問題:

1. Taro3 性能優化的方向

其實會上也有同學提到關于 Taro 在 3.4 版本推出支援了 preact,确實不論是 Taro-react 還是支援 preact 都是 Taro 在壓縮包體積方案中做出的嘗試,同時我們也打算通過 wasm 來提升 Taro3 在小程式中的性能。雖然 Taro3 目前還沒有官方的 benchmark,但也在籌備當中,敬請期待。

2. Taro3 的後續版本規劃與 Taro4

對于 Taro4 目前還無可奉告,但是在 Taro3 的後續版本特性,可以關注我們對外開放的 Task List,并對目前的 Feature Request 投票,對于很多開發中的新特性在這裡都能看到,當然大家如果什麼想法也可以在這裡送出,如果希望參與一些特性的研發工作,也歡迎大家送出 PR。

作者簡介

朱天健

京東零售平台業務中心 進階前端工程師

2019 年作為講師出席第二屆軟體綠色聯盟「構生态·建未來」開發者大會,2020 年受邀參加第四屆 TLC 騰訊直播大會。作為 Taro 架構的核心開發成員,主要負責多端元件庫及 API 相關的研發工作,同時負責開源社群管理機器人群控系統;Tide 項目的核心開發成員,主要負責 tide-site 和 cloud ide 相關的研發,第三方調用協定和相關接口,以及 Taro 相關的生态插件等。

活動推薦

2022 年 6 月 10-11 日,GMTC 北京站将與您再度相約!本次大會以“業務至上,效率為王”為主題,涵蓋前端性能優化、IoT 動态應用開發、TypeScript、移動端性能與效率優化等 15 個前沿技術專題,點選底部【閱讀全文】直達大會官網,更多精彩内容持續打磨上線中。大會門票 7 折限時優惠,立減 1440 元!感興趣的同學聯系票務經理:17310043226。

點個在看少個 bug

繼續閱讀