Taro 3 支持 React Native

2020-12-12 開源中國

項目背景

隨著 58 業務版圖不斷壯大,帶來的技術挑戰是怎麼在業務融合的過程中避免重複建設,提升開發以及多端落地效率,集團孵化了內部項目 58-rn,目前為止已經在組件化、開發流程優化、發布平臺建設以及線上監控預警等環節擁有一定積累。同時,Taro 是一款優秀的跨端開發框架,在 58 眾多產品線中都有使用,例如二手房、新房等。Taro 3 發布後暫不支持 React-Native 平臺,於是我們向社區提交了一份實現草案,希望把 58 在 React-Native 上的技術積累分享到社區,同時也從社區對 Taro 的共建上獲益。

特性

  1. 更純粹的 React Native 支持,社區生態對接更加簡便;
  2. 更好的 source-map 支持,開發調試體驗大幅提升;
  3. 更加完善的樣式寫法支持;
  4. 與 Taro 3 React 框架一致的運行時標準;
  5. 更豐富的 API 與組件,原生依賴支持按需引入;
  6. 高穩定高性能,源碼 TypeScript 開發、單元測試覆蓋全;

核心關注點

鑑於 Taro 良好的可擴展架構演化,適配 React-Native 變得更加容易。本文總結一些我們在設計上的新思考,希望能夠拋磚引玉。

Webpack or Metro?

Taro 目前的核心流程如下所示:


(出處:https://nervjs.github.io/taro/blog/2020-07-01-taro-3-0-0/)

我們做出了一點小改變,採用 metro 直接生成 bundle 文件;這與 WEB 端的處理類似。廣義上理解,針對小程序各端的處理也基本類似,只不過中間多了一步:先編譯成目標平臺的代碼,然後再用小程序 IDE 編譯發布。當然它與前兩者還是有些差異:目標平臺的中間代碼包含 Taro 運行時,調試起來並不是非常直觀;而前兩者直接生成最終打包資源,所以天然地支持 source-map 。 這一改變帶來的好處:

  1. 更好支持項目調試;打包資源中的運行時錯誤通過 source-map 直接與項目工程代碼對應,定位問題更直觀;

  2. Metro 更加貼合 React-Native 的打包場景:通過多級緩存以及 hasteFS 讓打包速度更快;

  3. React-Native 社區基於 Metro 的打包優化方案對接起來更容易;

現在情況變成了:WEB 和 React-Native 直接打包;小程序則使用端平臺插件機制進行擴展,生成目標平臺代碼,需要二次編譯才能發布。框架圖後半部分更新後看起來像這樣:

「零「 成本適配 React-Native 平臺

在討論方案之初,我們的目標之一:Taro3 項目只要升級框架版本就可以作為 React-Native 項目運行起來,無需對 Taro 項目模板進行任何修改;這保證了業務邏輯代碼以非常低的成本在 React-Native 端進行復用。當然我們沒法保證應用的運行效果完全符合預期;例如 CSS 標準中,子元素可以繼承其父元素的樣式,這在 React-Native 中並不適用;為此,我們支持編寫針對React-Native 平臺的專屬樣式。另外,React-Native 的樣式定義是 CSS 標準的子集,所以我們在編譯時會對 React-Native 不支持的樣式給出提示以及修復建議;這樣開發者就可以逐漸熟練編寫兼容多端的樣式。 最後,如果開發者仍然希望使用 React-Native/cli 的話,只需要修改 metro 配置就可以自由切換。目前,僅支持基於 React 編寫的應用「零」成本擴展到 React-Native 端。

促進社區融合

目前 Taro 和 React-Native 社區都主要以 WEB 開發者為主,但是側重點略有不同。Taro 主打 WEB 和小程序的融合,兼容多個應用開發框架,更偏向於小程序生態;React-Native 主打 React 生態,降低學習成本(learn once, write anywhere)。 Taro 1 和 2 做了大量工作來支持 React-Native,但是在開發體驗以及 API、組件適配程度上還需要進一步完善。我們在不影響 Taro 核心的情況下儘量解決這些痛點;例如,利用 expo 重構組件庫模塊 @tarojs/components-rn,重寫了 tab-bar 功能等。並開發獨立殼應用,本地不用配置原生開發環境也可以進行 React-Native 開發。對於 Taro 社區的開發者而言,應用可以 」無縫「 擴展到 React-Native 平臺;另一方面,React-Native 社區的開發者可以把 Taro 項目當作是 React-Native 應用的另一種項目模板,開發體驗」無縫「銜接。

新增組件 & API

最後但也是非常重要的一點,就是提升 Taro 組件和 API 規範在 React-Native 端的覆蓋度。要真正做到一套代碼,多端運行,核心在於組件 & API 規範的覆蓋度。我們支持基礎型組件(例如容器類、表單類等)的同時,也逐漸在進一步完善其它類型的組件以及 API。

tabbar & Navigator

tab 結構是最常用的頁面布局之一,僅僅通過 app 配置,就能生成一個多 tab 的 React-Native 頁面。

媒體組件

對於富有表現力的應用,總需要視頻、音頻以及相機組件的加持;我們已經把這些都集成進來了。

掃描二維碼

當下掃碼經濟如火如荼,基於開發者調研結果我們新增了 API scanCode,希望解決實際項目開發中的痛點。

長列表

React-Native 已經有非常成熟的方案來優化長列表,在此基礎上我們實現了組件 VirtualList。當開發者碰到長列表卡頓時,不妨嘗試這個新組件。

還有更多

PickerView 、MovableView等。

設計思路

現在分三種主要場景去闡述我們是怎麼實現「無縫「集成 React-Native 平臺的。

啟動 Dev Server

運行命令 yarn dev:rn 啟動 Metro bundle 伺服器時,

  1. @tarojs/cli 通過編譯平臺擴展 presets/platforms/rn.ts,啟動@tarojs/rn-runner

  2. @tarojs/rn-runner,它把 Taro 項目配置以及命令行參數轉換成 MetroServer 所需的配置,並與用戶自定義的 metro 配置合併(可選),然後啟動 MetroServer

訪問 bundle 文件

MetroServer 實質還是一個 HTTP 伺服器,當發起 /index.bundle 請求時,

  1. 如果是初次請求,IncrementalBundler 會初始化 DependencyGraph,掛載 hasteFS 的 change 事件,監聽文件變更;如果是非初次請求,IncrementalBundler 會生成當前請求模塊相關的變更集

  2. 在模塊處理過程中,@tarojs/rn-transformer 會針對入口文件和頁面文件進行特殊處理,主要是支持 tab-bar、app 以及頁面配置

  3. @tarojs/rn-style-transformer 會針對樣式進行處理,主要完成樣式語言 Sass/Less/Stylus 的覆蓋

  4. 等變更集中的模塊更新之後,重新讓當前模塊經過 Serializer 序列化成字符串返回

Bundle執行

當我們啟動 React-Native 原生 Android 應用時(iOS類似),

  1. CatalystInstanceImpl::runJSBundle 執行 bundle 的入口

  2. @tarojs/runtime-rn 調用 AppRegister.registerComponent 註冊頁面,並提供 API(@tarojs/taro-rn)和組件(@tarojs/components-rn)支持

如何使用?

如果你已經想使用 Taro3 開發 React-Native 應用的話,步驟非常簡單:

# 注意:@tarojs/cli 最新版本還未發布,體驗版在標籤 canary 下$ yarn add @tarojs/cli@canary# 創建並初始化 Taro 項目$ npx taro init <projectName># 設置環境變量DEVTAG,安裝體驗版相關依賴:$ export DEVTAG=@canary# 啟動 Dev Server,此處會顯示監聽埠號;支持 -p 選項手動指定埠$ cd <projectName> && yarn dev:rn

下載殼應用(https://github.com/NervJS/taro-native-shell/tree/0.63.2),然後構建並安裝到模擬器或真機上(以 android 為例):

# 安裝依賴$ yarn# 構建並啟動應用 $ yarn android -- --no-packager

如果缺少原生開發環境的話,直接下載應用安裝包即可:android 地址(https://share.weiyun.com/xB4OJiBw)。

依次執行 開發者菜單 -> Bundle Location 修改 bundle 的地址為 http://localhost:\ (埠號在執行 yarn dev:rn 時會在終端中輸出)就可以看到入口頁面了。

React-Native 相關調試以及常見使用問題請參考詳細文檔(https://taro-docs.jd.com/taro/docs/3.x/react-native/)。

如何升級?

3.x - 升級 @tarojs/cli 最新版本;把項目中 Taro 相關依賴包升級到最新版本;然後運行 yarn dev:rn, 此時會自動安裝 React-Native 相關依賴。

2.x - 先刪除 package.json 中 已存在的 React-Native 相關依賴項(@tarojs/rn-runner、@tarojs/runtime-rn、@taorjs/components-rn、@tarojs/router-rn 以及 @tarojs/taro-rn),然後按 3.x 的升級步驟即可。

如果升級過程中碰到問題,請通過末尾附上的渠道與我們溝通進行解決。

未來規劃

更高的 API、組件適配度

API、組件適配註定是一項耗時費力的長期工程,我們會繼續努力提升針對 React-Native 平臺的適配度。另外,也會關注組件性能問題,讓應用的操作體驗更加流暢。

動畫

動畫是 React-Native 持續優化的重要場景,我們會充分釋放其在這方面的優勢,提升 Taro 應用的交互體驗。

完善開發流程

目前我們主要解決了 Taro 擴展到 React-Native 端開發環節中的核心問題,後續會進一步支持項目的發布流程,集成熱更新、CI/CD 等功能。

如何貢獻 & 問題反饋

開發過程中我們採用了靜態類型約束(TypeScript)、單元測試(jest)以及靜態分析(ESLint)等措施儘量控制代碼質量,但是仍難免會有疏漏,非常期待大家的反饋並歡迎大家一起共建。另外,Taro 也提供了微信群方便大家與維護者們更及時溝通交流:

 

 


團隊簡介: 我們是 Taro3 適配 React-Native 平臺的開發團隊,來自房產事業群的多個 BU。主要成員:陳誌慶(項目發起人+架構)、葉春喜(開發姐姐)、邢智健(android)、王信健、郝捷、祝求智、張頁飛、錢傑(ios)、解成博、楊楊(測試妹子)、杜光中、羅正龍、陳昊。

相關焦點

  • React Native 0.63 發布,告警系統、顏色與交互能力改進
    pressable 組件React Native 現在支持 Web、桌面和電視等平臺,但是缺少對其它輸入方式的支持。為了解決在所有平臺上支持高質量的交互體驗,此版本提供了一個新核心組件Pressable。該組件可用於檢測各種類型的交互,旨在提供對交互當前狀態的直接訪問,而不必在父組件中手動維護狀態。
  • 「首席架構師推薦」關於React生態系統的一系列精選資源(3)
    模型庫mori - ClojureScript的持久數據結構和支持APINestedTypes - 具有「純渲染」支持的快速可變模型swarm - JavaScript複製模型(MVC的M)庫caplet - JavaScript模型庫數據管理Immutable.js
  • React系列(一) -邂逅React開發
    當應用的狀態發生改變時,通過setState來修改狀態,狀態發生變化時,UI會自動發生更新1.3.react多平臺1.3.2.其實呢,這三個庫是各司其職的,目的就是讓每一個庫只單純做自己的事情:在React的0.14版本之前是沒有react-dom這個概念的,所有功能都包含在react裡。為什麼要進行拆分呢?原因就是react-native。react包中包含了react和react-native所共同擁有的核心代碼。
  • Flutter,Native,React-Native,誰才是性能王中王?
    而選擇使用跨平臺,由於它有通用代碼庫,則可以顯著加快開發過程,使項目支持更加容易,並減少開發費用。但與跨平臺開發相比,單一開發的另一個優勢是性能。技術領域,可能會有「跨平臺應用程式速度慢」的刻板印象。實踐出真知,筆者決定測試一下這個說法是否真實,以及跨平臺應用程式比單一應用程式慢到什麼程度。
  • Flutter、React Native與Native: 深度性能的較量!
    用戶界面的動畫通常在不同的平臺上需要使用不同的工具,所以我們將範圍限制到每個平臺(只有一種情況除外)都支持的庫中,或者至少已盡己所能來實現這一點。當然,使用不同的運行方法可能會出現不一樣的測試結果。對某個領域真正的技術專家來說,一定可以把自己的一套測試工具運用得淋漓盡致,可能超過我們的測試結果。來看看我們的測試吧!
  • Shopify:用 React Native 打造移動應用開發的未來
    在今年的 BFCM 中,Shopify 商家在行動裝置上的購買量又增加了 3%,平均佔銷售額的 69%。那麼為什麼要切換到 React Native?為什麼現在切換?這一變化是如何融入我們的原生移動開發流程的?答案很複雜,我在回答這些問題之前需要先交代一些背景情況。
  • 芝麻醬佐味蒜香冰淇淋好吃到炸,TaroTaro甜品店讓你天天想「翻牌子」
    @Tarotaro Dessert and Tea House「暮光噩夢」最特別的是那個味覺衝擊點,如果你單吃聽起來讓人怕怕的大蒜冰淇淋,其實也是一種好味道。可是這最後淋上的特製的黑芝麻醬,國粹級的甜鹹味不僅完美融合了冰淇淋的蒜香奶味土司的香脆甜味,而且激發出三者彼此間的美妙化學反應,升華了整道甜點。
  • React SSR 同構入門與原理
    執行命令: create-react-app react-csr 創建一個 React SPA 單頁面應用項目 。執行命令: npm run start 啟動項目。{2}, useEffect Hook 中調用 getUserList 方法,獲取後臺真實數據{3},根據真實返回的 userList 渲染組件我們來看看實際效果:看起來很不錯, react-router
  • 精通react/vue組件設計之配合React Portals實現一個(Drawer)組件
    通過組件的設計過程,大家會接觸到一個完成健壯的組件設計思路和方法,也能在實現組件的過程逐漸對react/vue的高級知識和技巧有更深的理解和掌握,並且在企業實際工作做遊刃有餘.作為數據驅動的領導者react/vue等MVVM框架的出現,幫我們減少了工作中大量的冗餘代碼, 一切皆組件的思想深得人心.
  • 「無伺服器架構」Knative Serving 介紹
    Knative Serving建立在Kubernetes和Istio之上,以支持無伺服器應用程式和功能的部署和服務。服務易於上手,並且可以擴展以支持高級方案。服務資源Knative Serving將一組對象定義為Kubernetes自定義資源定義(CRD)。
  • React是什麼?React特點及框架整理(React一)-開課吧
    3. 靈活 -React可以與已知的庫或框架很好地配合。4. JSX -JSX是JavaScript語法的擴展。React開發不一定使用JSX,但我們建議使用它。5. 組件 -通過React構建組件,使得代碼更加容易得到復用,能夠很好的應用在大項目的開發中。6.
  • 值得選用的十三種優秀React JS框架
    該React組件支持更輕鬆、更快速的Web開發方式。有了它,您既可以自行構建設計系統,也可以從Material Design入手。3.Shards React這種現代化的React UI套件能夠提供快速的性能。
  • 「無伺服器架構」動手操作Knative -第2部分
    到目前為止,Knative支持從Kubernetes、GitHub、谷歌雲發布/訂閱、AWS SQS主題、容器和CronJobs讀取事件。一旦事件被拉入Knative,它就需要保存到內存中,或者保存到更持久的地方,比如Kafka或谷歌雲發布/訂閱。這發生在通道上。它有多個實現來支持不同的選項。
  • native produce是「土特產」,那「dairy produce」是啥意思呢?
    1、native produce這裡的produce應該做名詞「農產品、產品」等意思解釋,native是「本地的」,所以native produce就是指大家每次回老家都要帶的「土特產」。例句:Do you require to take some Chinese native produce?您想購買中國土特產業商品嗎?
  • 耐克react跑鞋耐磨嗎 耐克react跑鞋壽命為多少km
    耐克的緩震科技react是一款能夠和阿迪達斯的boost相提並論的科技,耐克的react跑鞋也是非常受歡迎的鞋款,那麼,耐克的react跑鞋的耐磨性怎麼樣呢?跑鞋的壽命又是多少呢?感興趣的朋友一起來看看吧!
  • 成為native speaker!
    回首學英語這條不歸路,我們一直在努力向native speaker靠攏。為了能夠在寫文章時更加「地道」,我們刻苦背記高級詞彙、鑽研高階語法;為了能夠在不經意間說出恰當的諺語,摘抄筆記寫了好幾頁紙。
  • 深入 React 的 setState 機制
    頁面顯示 count 的值為 3。在 setTimeout 裡面的首先拿到新的 count 值 2,再一次 setState,然後能實時拿到 count 的值為 3。在 perform 之前,先執行所有 wrapper 中的 initialize 方法;perform 完成之後(即 method 執行後)再執行所有的 close 方法,而且 Transaction 支持多個 wrapper 疊加。這就是 React 中的事務機制。
  • react
    react 3d模型 There is something in me that is amazed but beautiful 3D interfaces.sides) { return Math.ceil(width / (2 * Math.tan(Math.PI / sides))); }function magic(width, sides) { return Math.round(width * Math.log(sides)) }3.