跳到主要內容

React Native 每月精選 #5

·4 分鐘閱讀
Tomislav Tenodi
Speck 創辦人

React Native 每月會議持續進行!讓我們看看我們的團隊在做什麼。

Callstack

  • 我們一直在開發 React Native CI。最重要的是,我們已從 Travis 遷移到 Circle,為 React Native 留下單一、統一的 CI 管道。
  • 我們舉辦了Hacktoberfest - React Native 版本,我們與參與者一同嘗試提交許多提取請求到開放原始碼專案。
  • 我們持續開發 Haul。上個月,我們已提交兩個新版本,包括 webpack 3 支援。我們計劃加入 CRNAExpo 支援,以及開發更佳的 HMR。我們的藍圖公開在議題追蹤器上。如果您想要建議改進或提供意見回饋,請告訴我們!

Expo

  • 發布了 Expo SDK 22(使用 React Native 0.49)並為其更新了 CRNA
    • 包含改進的啟動畫面 API、基本 ARKit 支援、“DeviceMotion” API、iOS11 上的 SFAuthenticationSession 支援,以及更多
  • 您的 snacks 現在可以有多個 JavaScript 檔案,而且您只需將圖片和其他資產拖曳到編輯器中即可上傳。
  • 貢獻 react-navigation 以新增 iPhone X 的支援。
  • 將我們的注意力集中在以 Expo 建置大型應用程式時遇到的難題。例如
    • 一流的支援,可部署到多個環境:預備環境、生產環境和任意管道。管道將支援回溯和設定給定管道的活動版本。如果您想成為早期測試人員,請在 @expo_io 上告訴我們。
    • 我們也正在改進我們的獨立應用程式建置基礎架構,並新增對在獨立應用程式建置中捆綁圖片和其他非程式碼資產的支援,同時保持透過無線更新資產的能力。

Facebook

  • 更佳的 RTL 支援
    • 我們正在導入許多方向感知樣式。
      • 位置
        • (left|right) → (start|end)
      • 邊距
        • margin(Left|Right) → margin(Start|End)
      • 內距
        • padding(Left|Right) → padding(Start|End)
      • 邊框
        • borderTop(Left|Right)Radius → borderTop(Start|End)Radius
        • borderBottom(Left|Right)Radius → borderBottom(Start|End)Radius
        • border(Left|Right)Width → border(Start|End)Width
        • border(Left|Right)Color → border(Start|End)Color
    • 在 RTL 中,位置、邊距、內距和邊框樣式的“left”和“right”含義已交換。在幾個月內,我們將移除此行為,並讓“left”始終表示“left”,“right”始終表示“right”。重大變更隱藏在旗標下。在您的 React Native 組件中使用 I18nManager.swapLeftAndRightInRTL(false) 來選擇加入它們。
  • 正在開發 Flow,為我們的內部原生模組輸入類型,並使用這些類型在 Java 中產生介面,以及在 ObjC 中產生原生實作必須實作的協定。我們希望此程式碼產生能在明年(最早)開放原始碼。

Infinite Red

  • 新的 OSS 工具,用於協助 React Native 和其他專案。更多資訊請見此處
  • 改造 Ignite 以發布新的樣板(代號:Bowser)

Shoutem

  • 改善 Shoutem 上的開發流程。我們想要簡化從建立應用程式到第一個自訂畫面的流程,並使其非常容易,從而降低新 React Native 開發人員的門檻。準備了一些工作坊來測試新功能。我們也改進了 Shoutem CLI 以支援新流程。
  • Shoutem UI 收到了一些組件改進和錯誤修正。我們也檢查了與最新 React Native 版本的相容性。
  • Shoutem 平台收到了一些值得注意的更新,新的整合可作為開放原始碼擴充功能專案的一部分使用。我們很高興看到其他開發人員積極開發 Shoutem 擴充功能。我們主動聯繫並提供關於其擴充功能的建議和指導。

下次會議

下次會議安排在 2017 年 12 月 6 日星期三。如果您對我們應如何改進會議的輸出有任何建議,請隨時在 Twitter 上 ping 我。

React Native 每月精選 #4

·3 分鐘閱讀
Mike Grabowski
Mike Grabowski
Callstack 技術長暨共同創辦人

React Native 每月會議持續進行!以下是每個團隊的筆記

Callstack

  • React Native EU 已結束。來自 33 個國家/地區的 300 多名參與者造訪了弗羅茨瓦夫。演講可在 YouTube 上找到。
  • 會議結束後,我們正慢慢回到我們的開放原始碼排程。值得一提的是,我們正在開發 react-native-opentok 的下一個版本,該版本修正了大多數現有問題。

GeekyAnts

嘗試透過以下事項降低開發人員採用 React Native 的門檻

  • React Native EU 上宣布 BuilderX.io。BuilderX 是一個設計工具,可直接與 JavaScript 檔案(目前僅支援 React Native)搭配使用,以產生美觀、可讀且可編輯的程式碼。
  • 推出了 ReactNativeSeed.com,它為您的下一個 React Native 專案提供了一組樣板。它提供了多種選項,包括適用於資料類型的 TypeScript 和 Flow、適用於狀態管理的 MobX、Redux 和 mobx-state-tree,以及 CRNA 和純 React-Native 作為堆疊。

Expo

  • 即將發布 SDK 21,其中新增了對 react-native 0.48.3 的支援,以及 Expo SDK 中的一系列錯誤修正/可靠性改進/新功能,包括影片錄製、新的啟動畫面 API、對 react-native-gesture-handler 的支援,以及改進的錯誤處理。
  • 關於:react-native-gesture-handlerSoftware MansionKrzysztof Magiera 繼續推動此專案,我們一直在協助他測試並資助他部分開發時間。將其整合到 SDK21 中的 Expo 中將使人們能夠在 Snack 中輕鬆使用它,因此我們很高興看到人們會想出什麼。
  • 關於:改進的錯誤記錄/處理 - 請參閱 此內部 Expo PR 的 gist,以了解關於記錄的詳細資訊(特別是“問題 2”),以及 此 commit,以了解處理匯入 npm 標準函式庫模組失敗嘗試的變更。在 React Native 中以上述方式改進錯誤訊息有很多機會,我們將致力於後續的上游 PR。社群也能參與其中,那就太好了。
  • native.directory 繼續成長,您可以從 GitHub 儲存庫新增您的專案。
  • 造訪北美各地的黑客松,包括 PennAppsHack The NorthHackMIT,以及即將到來的 MHacks

Facebook

  • 致力於改進 Android 上的 <Text><TextInput> 組件。(<TextInput> 的原生自動成長;深度巢狀 <Text> 組件版面配置問題;更佳的程式碼結構;效能最佳化)。
  • 我們仍在尋找額外的貢獻者,他們願意協助分類議題和提取請求。

Microsoft

  • 發布了 CodePush 的程式碼簽署功能。React Native 開發人員現在能夠在 CodePush 中簽署其應用程式套件。公告可在此處找到
  • 致力於完成 CodePush 與 Mobile Center 的整合。也考慮測試/當機整合。

下次會議

下次會議安排在 2017 年 10 月 10 日星期三。由於這只是我們的第四次會議,我們想知道這些筆記對 React Native 社群有何益處。如果您對我們應如何改進會議的輸出有任何建議,請隨時在 Twitter 上 ping 我。

React Native 每月精選 #3

·5 分鐘閱讀
Mike Grabowski
Mike Grabowski
Callstack 技術長暨共同創辦人

React Native 每月會議持續進行!由於我們的大部分團隊都在忙於發布,因此本月的會議時間稍短。下個月,我們將在波蘭弗羅茨瓦夫舉行的 React Native EU 會議上。務必搶購門票,並在那裡與您親自見面!同時,讓我們看看我們的團隊在做什麼。

團隊

在第三次會議上,有 5 個團隊加入我們

筆記

以下是每個團隊的筆記

Callstack

  • 最近開放原始碼了 react-native-material-palette。它從圖片中提取顯著的色彩,以協助您建立視覺上引人入勝的應用程式。目前僅適用於 Android,但我們正在研究在未來新增對 iOS 的支援。
  • 我們已將 HMR 支援加入 haul 和一堆其他很棒的東西!查看最新版本。
  • React Native EU 2017 即將到來!下個月一切都將圍繞 React Native 和波蘭!務必搶購最後可用的門票此處

Expo

  • 發布了在 Snack 上安裝 npm 套件的支援。通常的 Expo 限制適用 - 套件不能依賴尚未包含在 Expo 中的自訂原生 API。我們也正在開發在 Snack 中支援多個檔案和上傳資產。Satyajit 將在 React Native Europe 上談論 Snack。
  • 發布了 SDK20,其中包含相機、付款、安全儲存、磁力計、暫停/恢復 fs 下載,以及改進的啟動/載入畫面。
  • 繼續與 Krzysztof 合作開發 react-native-gesture-handler。請試用一下,重建一些您先前使用 PanResponder 或原生手勢辨識器建置的手勢,並告知我們您遇到的問題。
  • 正在試驗 JSC 偵錯協定,並開發 Canny 上的一堆功能請求。

Facebook

  • 上個月,我們討論了 GitHub 議題追蹤器的管理,以及我們將嘗試進行改進以解決專案的可維護性問題。
  • 目前,未解決議題的數量穩定維持在大約 600 個,而且似乎可能會在一段時間內保持這種狀態。在過去一個月中,由於缺乏活動(定義為過去 60 天內沒有評論),我們已關閉 690 個議題。在這些 690 個議題中,有 58 個因各種原因而重新開啟(維護人員承諾提供修正,或貢獻者提出了保持議題開啟的絕佳理由)。
  • 我們計劃在可預見的未來繼續自動關閉過時的議題。我們希望達到一種狀態,即追蹤器中開啟的每個有影響力的議題都能得到處理,但我們尚未達到那種狀態。我們需要維護人員盡可能提供協助來分類議題,並確保我們不會錯過引入回歸或引入重大變更的議題,尤其是那些影響新建立專案的議題。有興趣提供協助的人員可以使用 Facebook GitHub Bot 來分類議題和提取請求。新的維護人員指南包含關於分類和使用 GitHub Bot 的更多資訊。請將自己新增到議題工作小組,並鼓勵其他活躍的社群成員也這樣做!

Microsoft

  • 新的 Skype 應用程式建立在 React Native 之上,以便於在平台之間盡可能多地共享程式碼。基於 React Native 的 Skype 應用程式目前在 Android 和 iOS 應用程式商店中提供。
  • 在 React Native 上建置 Skype 應用程式時,我們會將提取請求傳送給 React Native,以解決我們遇到的錯誤和遺失的功能。到目前為止,我們已合併約 70 個提取請求
  • React Native 使我們能夠從相同的程式碼庫為 Android 和 iOS Skype 應用程式提供支援。我們也想使用該程式碼庫來為 Skype Web 應用程式提供支援。為了協助我們實現該目標,我們在 React/React Native 之上建置並開放原始碼了一個薄層,稱為 ReactXP。ReactXP 提供了一組跨平台組件,在以 iOS/Android 為目標時,這些組件會對應到 React Native,而在以 Web 為目標時,則會對應到 react-dom。ReactXP 的目標與另一個名為 React Native for Web 的開放原始碼函式庫類似。在 ReactXP 常見問題中,簡要描述了這些函式庫的方法有何不同。

Shoutem

  • 我們正在繼續努力改善和簡化使用 Shoutem 建置應用程式時的開發人員體驗。
  • 開始將我們所有的應用程式遷移到 react-navigation,但我們最終將其推遲到發布更穩定的版本,或其中一個原生導航解決方案變得穩定為止。
  • 將我們所有的擴充功能和我們的大部分開放原始碼函式庫(animationthemeui)更新到 React Native 0.47.1。

下次會議

下次會議安排在 2017 年 9 月 13 日星期三。由於這只是我們的第三次會議,我們想知道這些筆記對 React Native 社群有何益處。如果您對我們應如何改進會議的輸出有任何建議,請隨時在 Twitter 上 ping 我。

React Native 在 Marketplace 的效能

·5 分鐘閱讀
Facebook 軟體工程師

React Native 用於 Facebook 系列多個應用程式的多個位置,包括主要 Facebook 應用程式中的頂層標籤。我們在此貼文中的重點是一個高度可見的產品,Marketplace。它在大約十幾個國家/地區提供,並讓使用者能夠探索其他使用者提供的產品和服務。

在 2017 年上半年,透過 Relay 團隊、Marketplace 團隊、Mobile JS Platform 團隊和 React Native 團隊的共同努力,我們將 Android Year Class 2010-11 裝置上的 Marketplace 互動時間 (TTI) 縮短了一半。Facebook 歷來將這些裝置視為低階 Android 裝置,而且它們在任何平台或裝置類型上都具有最慢的 TTI。

典型的 React Native 啟動看起來像這樣

免責聲明:比例不具代表性,並且會因 React Native 的配置和使用方式而異。

在執行產品特定的 JavaScript 之前,我們先初始化 React Native 核心(又稱“橋接器”),該 JavaScript 決定 React Native 將在原生處理時間中呈現哪些原生視圖。

不同的方法

我們早期犯下的錯誤之一是讓 Systrace 和 CTScan 驅動我們的效能工作。這些工具協助我們在 2016 年找到許多唾手可得的成果,但我們發現 Systrace 和 CTScan 都不能代表生產情境,也無法模擬野外發生的情況。分解中花費的時間比例通常不正確,有時甚至嚴重偏離。在極端情況下,我們預期需要幾毫秒才能完成的事情實際上需要數百或數千毫秒。也就是說,CTScan 很有用,而且我們發現它可以捕捉到三分之一的迴歸,然後才影響生產。

在 Android 上,我們將這些工具的缺點歸因於以下事實:1) React Native 是一個多執行緒框架,2) Marketplace 與大量複雜的視圖(例如 Newsfeed 和其他頂層標籤)共置,以及 3) 計算時間變化很大。因此,在這半年中,我們讓生產測量和分解幾乎驅動了我們所有的決策和優先順序。

生產儀器化的路徑

生產儀器化表面上聽起來很簡單,但事實證明這是一個相當複雜的過程。由於將 commit 提交到 master、將應用程式推送到 Play 商店,以及收集足夠的生產樣本以對我們的工作有信心,因此需要 2-3 週的多個迭代週期。每個迭代週期都涉及發現我們的分解是否準確、它們是否具有正確的粒度級別,以及它們是否正確地加總到整個時間跨度。我們無法依賴 alpha 版和 beta 版,因為它們不能代表一般大眾。本質上,我們非常乏味地基於數百萬個樣本的彙總,建置了一個非常準確的生產追蹤。

我們仔細驗證分解中的每一毫秒都正確加總到其父指標的原因之一是,我們很早就意識到我們的儀器化存在差距。事實證明,我們最初的分解並未考慮到執行緒跳躍造成的停頓。執行緒跳躍本身並不昂貴,但跳躍到已經在工作的繁忙執行緒非常昂貴。我們最終透過在正確的時刻灑上 Thread.sleep() 呼叫,在本地重現了這些阻塞,並且我們透過以下方式設法修正了它們

  1. 移除我們對 AsyncTask 的依賴,
  2. 取消在 UI 執行緒上強制初始化 ReactContext 和 NativeModules,以及
  3. 移除在初始化時測量 ReactRootView 的依賴。

總之,移除這些執行緒阻塞問題將啟動時間縮短了 25% 以上。

生產指標也挑戰了我們之前的一些假設。例如,我們過去常常在啟動路徑上預先載入許多 JavaScript 模組,假設將模組共置在一個套件中會降低其初始化成本。但是,預先載入和共置這些模組的成本遠遠超過了收益。透過重新配置我們的內嵌 require 黑名單並從啟動路徑中移除 JavaScript 模組,我們能夠避免載入不必要的模組,例如 Relay Classic(當只需要 Relay Modern 時)。如今,我們的 RUN_JS_BUNDLE 分解速度提高了 75% 以上。

我們也透過調查產品特定的原生模組找到了勝利。例如,透過延遲注入原生模組的依賴項,我們將該原生模組的成本降低了 98%。透過消除 Marketplace 啟動與其他產品的爭用,我們將啟動時間縮短了相當的時間間隔。

最棒的是,這些改進中有許多廣泛適用於所有使用 React Native 建構的畫面。

結論

人們認為 React Native 啟動效能問題是由於 JavaScript 速度緩慢或網路時間過長所導致。雖然加速 JavaScript 等項目可以顯著降低 TTI,但與先前認為的相比,這些因素對 TTI 的貢獻百分比較小。

目前為止的教訓是衡量、衡量、再衡量! 一些成果來自於將執行時期成本轉移到建置時期,例如 Relay Modern 和 Lazy NativeModules。其他成果來自於更聰明地平行化程式碼或移除無效程式碼來避免工作。還有些成果來自於 React Native 的大型架構變更,例如清理執行緒阻塞。效能沒有萬能的解決方案,而長期的效能提升將來自於漸進式的效能監測和改進。不要讓認知偏誤影響您的決策。相反地,請仔細收集和解讀生產數據,以指導未來的工作。

未來計畫

從長遠來看,我們希望 Marketplace TTI 能與使用 Native 建構的類似產品相提並論,並且總體而言,讓 React Native 的效能與原生效能相當。此外,儘管這半年我們大幅降低了橋接啟動成本約 80%,但我們計畫透過 Prepack 等專案和更多建置時期處理,將 React Native 橋接的成本降至接近於零。

React Native 每月精選 #2

·8 分鐘閱讀
Tomislav Tenodi
Shoutem 產品經理

React Native 每月例會持續進行中!在這次會議中,我們邀請了 Infinite RedChain React, the React Native Conference 背後的大腦。由於這裡的大多數人都在 Chain React 上發表演講,我們將會議推遲了一週。會議的演講已發布到網路上,我鼓勵您去看看。那麼,讓我們看看我們的團隊正在做什麼。

團隊

在第二次會議中,我們有 9 個團隊加入我們

筆記

以下是每個團隊的筆記

Airbnb

Callstack

  • Mike Grabowski 一如既往地管理 React Native 的每月發布,包括發布了一些 beta 版本。特別是,致力於發布 v0.43.5 build 到 npm,因為它可以解除 Windows 使用者的封鎖!
  • Haul 上正在進行緩慢但持續的工作。有一個 pull request 添加了 HMR,並且其他改進也已發布。最近獲得了一些業界領導者的採用。可能計畫開始在該領域進行全職有償工作。
  • 來自 Jest 團隊的 Michał Pierzchała 本月加入了 Callstack。他將協助維護 Haul,並可能參與 Metro BundlerJest 的工作。
  • Satyajit Sahoo 現在與我們同在,耶!
  • 從我們的 OSS 部門獲得了一堆很酷的東西。特別是,致力於將 Material Palette API 引入 React Native。計畫最終發布我們的原生 iOS 套件,旨在提供與原生元件 1:1 的外觀和風格。

Expo

  • 最近推出了 Native Directory,以協助在 React Native 生態系統中發現和評估函式庫。問題是:函式庫很多,難以測試,需要手動應用啟發法,並且不容易立即看出哪些是您應該使用的最佳函式庫。也很難知道某個東西是否與 CRNA/Expo 相容。因此,Native Directory 試圖解決這些問題。查看一下並新增您的函式庫到其中。函式庫列表在這裡。這只是我們的初步嘗試,我們希望這由社群擁有和營運,而不僅僅是 Expo 的人員。因此,如果您認為這很有價值並希望使其變得更好,請盡一份心力!
  • 在 Expo SDK 19 的 Snack 中新增了安裝 npm 套件的初始支援。如果您在使用時遇到任何問題,請告訴我們,我們仍在處理一些錯誤。連同 Native Directory,這應該可以輕鬆測試僅具有 JS 依賴項或包含在 Expo SDK 中的依賴項的函式庫。試用看看
  • 發布了 Expo SDK19,其中包含各方面的許多改進,我們現在正在使用更新的 Android JSC
  • 正在與 Alexander Kotliarskyi 一起在文件中編寫指南,其中列出了關於如何改進您的應用程式使用者體驗的技巧。請加入並添加到列表中或協助撰寫部分內容!
  • 持續致力於:音訊/視訊、相機、手勢(與 Software Mansion 合作,react-native-gesture-handler)、GL 相機整合,並希望在 SDK20(八月)中首次實現其中一些功能,並在屆時對其他功能進行重大改進。我們才剛開始在 Expo 用戶端中建構基礎架構,以用於背景工作(地理位置、音訊、處理通知等)。
  • Adam Miskiewicz 在模仿 react-navigationUINavigationController 的轉場效果方面取得了一些不錯的進展。查看他在 他的推文 中的早期版本 - 版本即將發布。另請查看他向上游推送MaskedViewIOS。如果您有技能和意願為 Android 實作 MaskedView,那就太棒了!

Facebook

  • Facebook 正在內部探索是否能夠在 React Native 內部嵌入原生 ComponentKitLitho 元件。
  • 非常歡迎對 React Native 做出貢獻!如果您想知道如何貢獻,「如何貢獻」指南描述了我們的開發流程,並列出了發送您的第一個 pull request 的步驟。還有其他不需要編寫程式碼的貢獻方式,例如分類 issue 或更新文件。
    • 在撰寫本文時,React Native 有 635開啟的 issue249開啟的 pull request。這對我們的維護者來說是壓倒性的,而且當問題在內部修復時,很難確保相關任務得到更新。
    • 我們不確定在讓社群滿意的情況下,處理這個問題的最佳方法是什麼。一些(但不是全部!)選項包括關閉過時的 issue、給予更多人管理 issue 的權限,以及自動關閉不遵循 issue 範本的 issue。我們撰寫了「對維護者的期望」指南,以設定期望並避免意外。如果您對如何改善維護者的體驗,以及確保開啟 issue 和 pull request 的人員感到被傾聽和重視有任何想法,請告訴我們!

GeekyAnts

  • 我們在 Chain React 上示範了適用於 React Native 檔案的 Designer Tool。許多與會者報名了候補名單。
  • 我們也在研究其他跨平台解決方案,例如 Google Flutter(即將進行重大比較)、Kotlin NativeApache Weex,以了解架構上的差異,以及我們可以從中學習什麼來改進 React Native 的整體效能。
  • 我們的大多數應用程式都切換到 react-navigation,這提高了整體效能。
  • 此外,還發布了 NativeBase Market - 一個適用於 React Native 元件和應用程式的市場(適用於開發人員並由開發人員開發)。

Infinite Red

Microsoft

  • CodePush 現在已整合到 Mobile Center 中。現有使用者的工作流程不會有任何變更。
    • 有些人回報了應用程式重複的問題 - 他們在 Mobile Center 上已經有一個應用程式。我們正在努力解決這些問題,但如果您有兩個應用程式,請告訴我們,我們可以為您合併它們。
  • Mobile Center 現在支援 CodePush 的推播通知。我們還展示了如何將通知和 CodePush 結合使用來進行應用程式的 A/B 測試 - 這是 ReactNative 架構獨有的功能。
  • VS Code 在 ReactNative 中存在已知的偵錯問題 - 幾天後發布的下一個擴充功能版本將修復該問題。
  • 由於 Microsoft 內部還有許多其他團隊也在從事 React Native 的工作,我們將努力在下次會議中獲得所有團隊更好的代表性。

Shoutem

  • 完成了在 Shoutem 上簡化 React Native 開發的流程。在 Shoutem 上開發應用程式時,您可以使用所有標準的 react-native 命令。
  • 我們做了大量工作,試圖找出在 React Native 上進行效能分析的最佳方法。文件的大部分內容都已過時,我們將盡力在官方文件中建立 pull request,或至少在部落格文章中寫下我們的一些結論。
  • 將我們的導航解決方案切換到 react-navigation,因此我們可能很快就會收到一些回饋。
  • 我們在我們的工具組中發布了一個新的 HTML 元件,該元件將原始 HTML 轉換為 React Native 元件樹。

Wix

  • 我們開始致力於向 Metro Bundler 發送 pull request,其中包含 react-native-repackager 功能。我們更新了 react-native-repackager 以支援 RN 44(我們在生產環境中使用)。我們將其用於 detox 的模擬基礎架構。
  • 在過去的三週裡,我們一直在 detox 測試中涵蓋 Wix 應用程式。這是一個驚人的學習經驗,了解如何在這種規模的應用程式(超過 40 位工程師)中減少手動 QA。我們因此解決了 detox 的幾個問題,並且剛剛發布了一個新版本。我很樂意報告,我們遵守了「零不穩定性原則」,並且到目前為止,測試一直穩定通過。
  • Android 版 Detox 正在順利推進。我們正在獲得社群的大力協助。我們預計在大約兩週內推出初始版本。
  • DetoxInstruments,我們的效能測試工具,正變得比我們最初預期的要大一些。我們現在計畫將其轉變為獨立工具,而不是與 detox 緊密耦合。它將允許調查 iOS 應用程式的整體效能。它也將與 detox 整合,以便我們可以對效能指標執行自動化測試。

下次會議

下一次會議定於 2017 年 8 月 16 日。由於這只是我們的第二次會議,我們想知道這些筆記對 React Native 社群有何益處。如果您對我們應該如何改進會議的產出有任何建議,請隨時在 Twitter 上 ping 我。

React Native 每月精選 #1

·6 分鐘閱讀
Tomislav Tenodi
Shoutem 產品經理

Shoutem,我們很幸運能夠從 React Native 的最初期就開始使用它。我們決定從一開始就成為這個令人驚嘆的社群的一份子。很快地,我們意識到幾乎不可能跟上社群成長和改進的步伐。這就是為什麼我們決定組織每月例會,讓所有主要的 React Native 貢獻者可以簡要介紹他們的工作和計畫。

每月例會

我們於 2017 年 6 月 14 日舉行了第一次每月例會。React Native Monthly 的使命簡單明瞭:改進 React Native 社群。團隊展示他們的工作有助於促進團隊之間線下的協作。

團隊

在第一次會議中,我們有 8 個團隊加入我們

我們希望有更多核心貢獻者加入即將到來的會議!

筆記

由於團隊的計畫可能會引起更廣泛受眾的興趣,我們將在這裡(React Native 部落格上)分享它們。所以,以下是它們

Airbnb

  • 計畫在 ViewAccessibilityInfo 原生模組中新增一些 A11y(協助工具)API。
  • 將研究在 Android 上的原生模組中新增一些 API,以允許指定它們運行的執行緒。
  • 一直在研究潛在的初始化效能改進。
  • 一直在研究一些更複雜的捆綁策略,以用於「unbundle」之上。

Callstack

  • 正在研究使用 Detox 進行 E2E 測試,以改進發布流程。Pull request 應該很快就會提交。
  • 他們一直在處理的 Blob pull request 已合併,後續的 pull request 即將推出。
  • 在內部專案中增加 Haul 的採用率,以了解它與 Metro Bundler 相比的效能。正在與 webpack 團隊合作,以提高多執行緒效能。
  • 在內部,他們實作了更好的基礎架構來管理開源專案。計畫在未來幾週內發布更多內容。
  • React Native Europe 會議即將到來,目前還沒有什麼有趣的事情,但邀請大家參加!
  • 暫時退出了 react-navigation 一段時間,以研究替代方案(尤其是原生導航)。

Expo

  • 正在努力使在 Snack 中安裝 npm 模組成為可能,這對於函式庫在文件中新增範例會很有用。
  • 正在與 KrzysztofSoftware Mansion 的其他人合作,進行 Android 上的 JSC 更新和手勢處理函式庫。
  • Adam Miskiewicz 正在將他的重點轉向 react-navigation
  • Create React Native App 位於文件中的入門指南中。Expo 希望鼓勵函式庫作者清楚地說明他們的函式庫是否適用於 CRNA,如果適用,請說明如何設定它。

Facebook

  • React Native 的打包器現在是 Metro Bundler,位於獨立的儲存庫中。倫敦的 Metro Bundler 團隊很高興能滿足社群的需求、改進 React Native 以外的其他使用案例的模組化,並提高對 issue 和 PR 的回應速度。
  • 在接下來的幾個月中,React Native 團隊將致力於改進原始元件的 API。預期在版面配置怪癖、協助工具和 Flow 型別方面有所改進。
  • React Native 團隊也計畫在今年透過重構完全支援 Windows 和 macOS 等第三方平台,來改進核心模組化。

GeekyAnts

  • 該團隊正在開發一個 UI/UX 設計應用程式(代號:Builder),它可以直接處理 .js 檔案。目前,它僅支援 React Native。它類似於 Adobe XD 和 Sketch。
  • 該團隊正在努力讓您可以將現有的 React Native 應用程式載入到編輯器中,進行變更(視覺上,作為設計師),並將變更直接儲存到 JS 檔案中。
  • 人們正在嘗試彌合設計師和開發人員之間的差距,並將他們放在同一個儲存庫中。
  • 此外,NativeBase 最近達到了 5,000 個 GitHub 星星。

Microsoft

  • CodePush 現在已整合到 Mobile Center 中。這是為分發、分析和其他服務提供更整合體驗的第一步。請參閱他們的公告這裡
  • VS Code 在偵錯方面存在錯誤,他們目前正在努力修復該錯誤,並將推出新的 build。
  • 正在研究 Detox 以進行整合測試,並查看 JSC Context 以取得與當機報告一起的變數。

Shoutem

  • 讓使用 React Native 社群工具在 Shoutem 應用程式上工作變得更容易。您將可以使用所有 React Native 命令來執行在 Shoutem 上建立的應用程式。
  • 正在研究 React Native 的效能分析工具。他們在設定時遇到了很多問題,他們將寫下他們在此過程中發現的一些見解。
  • Shoutem 正在努力使將 React Native 與現有原生應用程式整合變得更容易。他們將記錄他們在公司內部開發的概念,以便獲得社群的回饋。

Wix

  • 正在內部採用 Detox,以將 Wix 應用程式的很大一部分轉移到「零手動 QA」。因此,Detox 正在被數十名開發人員在生產環境中大量使用,並且正在迅速成熟。
  • 致力於在 Metro Bundler 中新增對在建置期間覆寫任何檔案副檔名的支援。它不僅僅支援「ios」和「android」,還將支援任何自訂副檔名,例如「e2e」或「detox」。計畫將其用於 E2E 模擬。已經有一個名為 react-native-repackager 的函式庫,現在正在處理 PR。
  • 正在研究效能測試的自動化。這是一個名為 DetoxInstruments 的新儲存庫。您可以看看,它正在開源開發中。
  • 正在與來自 KPN 的貢獻者合作開發 Android 版 Detox 並支援真實裝置。
  • 正在考慮將「Detox 作為平台」,以允許建構其他需要自動化模擬器/裝置的工具。一個範例是 React Native 的 Storybook 或 Ram 關於整合測試的想法。

下次會議

會議將每四周舉行一次。下一次會議定於 2017 年 7 月 12 日。由於我們才剛開始這次會議,我們想知道這些筆記對 React Native 社群有何益處。如果您對我們應該在後續會議中涵蓋哪些內容,或我們應該如何改進會議的產出有任何建議,請隨時在 Twitter 上 ping 我。

更佳的 React Native 列表視圖

·6 分鐘閱讀
Spencer Ahrens
Facebook 軟體工程師

在我們於社群群組中發布預告公告後,你們中的許多人已經開始試用我們的一些新 List 元件,但我們今天正式宣布它們!不再有 ListViewDataSource、過時的列、被忽略的錯誤或過多的記憶體消耗 - 使用最新的 React Native 2017 年 3 月候選發行版 (0.43-rc.1),您可以從新的元件套件中選擇最適合您使用案例的元件,並具有出色的效能和開箱即用的功能集

<FlatList>

這是用於簡單、高效能列表的工作主力元件。提供資料陣列和 renderItem 函數,您就可以開始使用了

<FlatList
data={[{title: 'Title Text', key: 'item1'}, ...]}
renderItem={({item}) => <ListItem title={item.title} />}
/>

<SectionList>

如果您想呈現一組分成邏輯區段的資料,可能帶有區段標頭(例如,在字母順序的地址簿中),並且可能具有異質資料和呈現(例如,帶有一些按鈕的個人資料檢視,然後是撰寫器,然後是照片網格,然後是朋友網格,最後是故事列表),這是最佳選擇。

<SectionList
renderItem={({item}) => <ListItem title={item.title} />}
renderSectionHeader={({section}) => <H1 title={section.key} />}
sections={[ // homogeneous rendering between sections
{data: [...], key: ...},
{data: [...], key: ...},
{data: [...], key: ...},
]}
/>

<SectionList
sections={[ // heterogeneous rendering between sections
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
]}
/>

<VirtualizedList>

幕後實作具有更靈活的 API。如果您的資料不在純陣列中(例如,不可變列表),則特別方便。

功能

列表在許多情況下使用,因此我們在新元件中加入了完整的功能,以處理大多數開箱即用的使用案例

  • 滾動載入 (onEndReached)。
  • 下拉刷新 (onRefresh / refreshing)。
  • 可配置的可見性 (VPV) 回呼 (onViewableItemsChanged / viewabilityConfig)。
  • 水平模式 (horizontal)。
  • 智慧型項目和區段分隔符。
  • 多欄支援 (numColumns)
  • scrollToEndscrollToIndexscrollToItem
  • 更好的 Flow 型別。

一些注意事項

  • 當內容滾動出渲染視窗時,項目子樹的內部狀態不會被保留。確保您的所有資料都捕獲在項目資料或 Flux、Redux 或 Relay 等外部儲存區中。

  • 這些元件基於 PureComponent,這表示如果 props 保持淺層相等,它們將不會重新渲染。確保您的 renderItem 函數直接依賴的所有內容都作為 prop 傳遞,該 prop 在更新後不是 ===,否則您的 UI 可能不會在變更時更新。這包括 data prop 和父元件狀態。例如

    <FlatList
    data={this.state.data}
    renderItem={({item}) => (
    <MyItem
    item={item}
    onPress={() =>
    this.setState(oldState => ({
    selected: {
    // New instance breaks `===`
    ...oldState.selected, // copy old data
    [item.key]: !oldState.selected[item.key], // toggle
    },
    }))
    }
    selected={
    !!this.state.selected[item.key] // renderItem depends on state
    }
    />
    )}
    selected={
    // Can be any prop that doesn't collide with existing props
    this.state.selected // A change to selected should re-render FlatList
    }
    />
  • 為了限制記憶體並實現流暢滾動,內容會異步地在螢幕外渲染。這表示滾動速度可能快於填充速度,並且可能會短暫看到空白內容。這是一種權衡,可以調整以滿足每個應用程式的需求,我們正在幕後努力改進它。

  • 預設情況下,這些新列表會在每個項目上尋找 key prop,並將其用於 React key。或者,您可以提供自訂的 keyExtractor prop。

效能

除了簡化 API 之外,新的列表元件還具有顯著的效能增強功能,主要功能是對於任何數量的列,記憶體使用量幾乎恆定。這是透過「虛擬化」渲染視窗外的元素來完成的,方法是將它們完全從元件層次結構中卸載,並從 react 元件中回收 JS 記憶體,以及從陰影樹和 UI 檢視中回收原生記憶體。這有一個缺點,即內部元件狀態將不會被保留,因此請確保您在元件本身之外追蹤任何重要狀態,例如在 Relay 或 Redux 或 Flux 儲存區中。

限制渲染視窗也減少了 React 和原生平台需要完成的工作量,例如來自檢視遍歷。即使您正在渲染一百萬個元素的最後一個,使用這些新列表也不需要迭代所有這些元素才能進行渲染。您甚至可以使用 scrollToIndex 跳到中間,而無需過度渲染。

我們還對排程進行了一些改進,這應該有助於應用程式的響應能力。渲染視窗邊緣的項目會不頻繁地渲染,並且在任何活動手勢或動畫或其他互動完成後,會以較低的優先級渲染。

進階用法

ListView 不同,渲染視窗中的所有項目會在任何 props 變更時重新渲染。通常這很好,因為視窗化將項目數量減少到恆定數量,但如果您的項目比較複雜,您應該確保遵循 React 效能最佳實踐,並在您的元件中適當地使用 React.PureComponent 和/或 shouldComponentUpdate,以限制遞迴子樹的重新渲染。

如果您可以在不渲染列的情況下計算列的高度,則可以透過提供 getItemLayout prop 來改善使用者體驗。這使得使用 scrollToIndex 等方式滾動到特定項目時更加流暢,並且將改善滾動指示器 UI,因為可以在不渲染內容的情況下確定內容的高度。

如果您有替代資料型別,例如不可變列表,<VirtualizedList> 是最佳選擇。它採用 getItem prop,讓您可以傳回任何給定索引的項目資料,並具有較寬鬆的 flow 型別。

如果您有不尋常的使用案例,還可以調整許多參數。例如,您可以使用 windowSize 來權衡記憶體使用量與使用者體驗、使用 maxToRenderPerBatch 來調整填充率與響應能力、使用 onEndReachedThreshold 來控制滾動載入何時發生等等。

未來工作

  • 現有介面的遷移(最終將棄用 ListView)。
  • 更多功能,當我們看到/聽到需求時(請告訴我們!)。
  • 黏性區段標頭支援。
  • 更多效能最佳化。
  • 支援具有狀態的功能性項目元件。

idx:存在函數

·2 分鐘閱讀
Timothy Yung
Facebook 工程經理

在 Facebook,我們經常需要存取使用 GraphQL 提取的資料結構中深度巢狀的值。在存取這些深度巢狀值的過程中,一個或多個中間欄位通常是可為 null 的。這些中間欄位可能因多種原因而為 null,從隱私權檢查失敗到 null 恰好是表示非致命錯誤的最靈活方式。

不幸的是,目前存取這些深度巢狀值既繁瑣又冗長。

props.user &&
props.user.friends &&
props.user.friends[0] &&
props.user.friends[0].friends;

一個 ECMAScript 提案,旨在引入存在運算符,這將使這一切更加方便。但在該提案最終確定之前,我們需要一個可以提高我們的生活品質、維護現有語言語意並鼓勵 Flow 的型別安全性的解決方案。

我們 придумали 一個我們稱之為 idx 的存在性函式

idx(props, _ => _.user.friends[0].friends);

此程式碼片段中的調用行為與上述程式碼片段中的布林運算式類似,但重複性顯著降低。 idx 函式正好接受兩個引數

  • 任何值,通常是您想要存取巢狀值的物件或陣列。
  • 一個函式,它接收第一個引數並存取其上的巢狀值。

理論上,idx 函式會嘗試捕獲 (try-catch) 因存取 null 或 undefined 上的屬性而產生的錯誤。如果捕獲到此類錯誤,它將傳回 null 或 undefined。(您可以在 idx.js 中查看如何實作。)

實際上,對每個巢狀屬性存取都進行 try-catch 操作速度很慢,並且區分特定類型的 TypeError 非常脆弱。為了應對這些缺點,我們建立了一個 Babel 外掛程式,將上面的 idx 調用轉換為以下運算式

props.user == null
? props.user
: props.user.friends == null
? props.user.friends
: props.user.friends[0] == null
? props.user.friends[0]
: props.user.friends[0].friends;

最後,我們為 idx 新增了一個自訂 Flow 型別宣告,允許在第二個引數中進行遍歷時進行適當的型別檢查,同時允許對可為 null 的屬性進行巢狀存取。

此函式、Babel 外掛程式和 Flow 宣告現在已在 GitHub 上提供。它們的使用方式是安裝 idxbabel-plugin-idx npm 套件,並將 “idx” 新增到您的 .babelrc 檔案中的外掛程式列表中。

介紹 Create React Native App

·2 分鐘閱讀
Adam Perry
Expo 軟體工程師

今天我們宣布推出 Create React Native App:這是一個新的工具,可以顯著簡化 React Native 專案的入門!它深受 Create React App 設計的啟發,並且是 FacebookExpo(前身為 Exponent)之間合作的產品。

許多開發人員在安裝和設定 React Native 目前的原生建置相依性時遇到困難,尤其是在 Android 上。使用 Create React Native App,無需使用 Xcode 或 Android Studio,並且您可以使用 Linux 或 Windows 為您的 iOS 裝置進行開發。這是透過 Expo 應用程式完成的,該應用程式載入並執行以純 JavaScript 撰寫的 CRNA 專案,而無需編譯任何原生程式碼。

嘗試建立一個新專案(如果您已安裝 yarn,請替換為適當的 yarn 指令)

$ npm i -g create-react-native-app
$ create-react-native-app my-project
$ cd my-project
$ npm start

這將啟動 React Native 封裝器並列印 QR 碼。在 Expo 應用程式中開啟它以載入您的 JavaScript。對 console.log 的呼叫會轉發到您的終端機。您可以使用任何標準 React Native API 以及 Expo SDK

原生程式碼呢?

許多 React Native 專案都有需要編譯的 Java 或 Objective-C/Swift 相依性。Expo 應用程式確實包含用於相機、影片、聯絡人等的 API,並捆綁了流行的程式庫,例如 Airbnb 的 react-native-mapsFacebook 驗證。但是,如果您需要 Expo 未捆綁的原生程式碼相依性,那麼您可能需要為其設定自己的建置組態。就像 Create React App 一樣,CRNA 支援「彈出 (ejecting)」。

您可以執行 npm run eject 來取得一個與 react-native init 將產生的專案非常相似的專案。在那時,您將需要 Xcode 和/或 Android Studio,就像您從 react-native init 開始一樣,使用 react-native link 新增程式庫將會起作用,並且您將完全控制原生程式碼編譯過程。

有問題嗎?意見回饋?

Create React Native App 現在已足夠穩定,可以廣泛使用,這表示我們非常渴望聽到您使用它的體驗!您可以在 Twitter 上找到我,或在 GitHub 儲存庫上開啟 issue。非常歡迎提交 Pull Request!

將 Native Driver 用於 Animated

·7 分鐘閱讀
Janic Duplessis
App & Flow 軟體工程師

在過去一年中,我們一直致力於改進使用 Animated 程式庫的動畫效能。動畫對於創造美觀的使用者體驗非常重要,但也可能難以正確地完成。我們希望讓開發人員能夠輕鬆建立高效能的動畫,而無需擔心他們的某些程式碼會導致動畫延遲。

這是什麼?

Animated API 的設計考慮到一個非常重要的限制,它是可序列化的。這表示我們可以在動畫甚至開始之前將所有關於動畫的內容傳送到原生,並允許原生程式碼在 UI 執行緒上執行動畫,而無需在每個影格上都通過橋接器。這非常有用,因為一旦動畫開始,JS 執行緒可能會被封鎖,而動畫仍然會流暢地運行。實際上,這種情況可能會經常發生,因為使用者程式碼在 JS 執行緒上運行,並且 React 渲染也可能會長時間鎖定 JS。

一點歷史...

這個專案大約在一年前開始,當時 Expo 在 Android 上建置了 li.st 應用程式。Krzysztof Magiera 受聘在 Android 上建置初始實作。它最終運作良好,li.st 是第一個使用 Animated 交付原生驅動動畫的應用程式。幾個月後,Brandon Withrow 在 iOS 上建置了初始實作。在那之後,Ryan Gomba 和我致力於新增遺失的功能,例如支援 Animated.event,以及修正我們在生產應用程式中使用它時發現的錯誤。這確實是一個社群努力,我要感謝所有參與者以及 Expo 對開發的大部分贊助。React Native 中的 Touchable 元件以及新發布的 React Navigation 程式庫中的導航動畫現在都使用了它。

它是如何運作的?

首先,讓我們看看目前使用 Animated 和 JS 驅動程式的動畫是如何運作的。當使用 Animated 時,您宣告一個節點圖,表示您想要執行的動畫,然後使用驅動程式使用預定義的曲線更新 Animated 值。您也可以透過將 Animated 值連接到 View 的事件來更新它,使用 Animated.event

以下是動畫步驟及其發生位置的分解

  • JS:動畫驅動程式使用 requestAnimationFrame 在每個影格上執行,並使用根據動畫曲線計算出的新值來更新它驅動的值。
  • JS:計算中間值並將其傳遞到附加到 View 的 props 節點。
  • JS:使用 setNativeProps 更新 View
  • JS 到原生橋接器。
  • 原生:更新 UIViewandroid.View

如您所見,大部分工作都在 JS 執行緒上完成。如果它被封鎖,動畫將會跳過影格。它還需要在每個影格上通過 JS 到原生橋接器來更新原生視圖。

原生驅動程式所做的是將所有這些步驟移至原生。由於 Animated 產生了動畫節點圖,因此它可以序列化並在動畫開始時僅傳送一次到原生,從而消除了回調到 JS 執行緒的需要;原生程式碼可以負責在每個影格上直接在 UI 執行緒上更新視圖。

以下是我們如何序列化動畫值和插值節點的範例(不是確切的實作,只是一個範例)。

建立原生值節點,這是將要動畫化的值

NativeAnimatedModule.createNode({
id: 1,
type: 'value',
initialValue: 0,
});

建立原生插值節點,這會告訴原生驅動程式如何插值一個值

NativeAnimatedModule.createNode({
id: 2,
type: 'interpolation',
inputRange: [0, 10],
outputRange: [10, 0],
extrapolate: 'clamp',
});

建立原生 props 節點,這會告訴原生驅動程式它附加到的視圖上的哪個 prop

NativeAnimatedModule.createNode({
id: 3,
type: 'props',
properties: ['style.opacity'],
});

將節點連接在一起

NativeAnimatedModule.connectNodes(1, 2);
NativeAnimatedModule.connectNodes(2, 3);

將 props 節點連接到視圖

NativeAnimatedModule.connectToView(3, ReactNative.findNodeHandle(viewRef));

有了這些,原生動畫模組就擁有更新原生視圖所需的所有資訊,而無需去 JS 計算任何值。

剩下要做的就是實際啟動動畫,方法是指定我們想要的動畫曲線類型以及要更新的動畫值。計時動畫也可以透過在 JS 中預先計算動畫的每個影格來簡化,以使原生實作更小。

NativeAnimatedModule.startAnimation({
type: 'timing',
frames: [0, 0.1, 0.2, 0.4, 0.65, ...],
animatedValueId: 1,
});

現在,以下是動畫運行時發生的情況的分解

  • 原生:原生動畫驅動程式使用 CADisplayLinkandroid.view.Choreographer 在每個影格上執行,並使用根據動畫曲線計算出的新值來更新它驅動的值。
  • 原生:計算中間值並將其傳遞到附加到原生視圖的 props 節點。
  • 原生:更新 UIViewandroid.View

如您所見,不再有 JS 執行緒和橋接器,這表示動畫更快了!🎉🎉

我如何在我的應用程式中使用它?

對於正常動畫,答案很簡單,只需在啟動動畫時將 useNativeDriver: true 新增到動畫組態中即可。

之前

Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 500,
}).start();

之後

Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 500,
useNativeDriver: true, // <-- Add this
}).start();

Animated 值僅與一個驅動程式相容,因此如果您在使用原生驅動程式啟動值上的動畫時,請確保該值上的每個動畫也使用原生驅動程式。

它也適用於 Animated.event,如果您有一個動畫必須跟隨滾動位置,這非常有用,因為如果沒有原生驅動程式,由於 React Native 的非同步性質,它始終會比手勢落後一個影格。

之前

<ScrollView
scrollEventThrottle={16}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.animatedValue } } }]
)}
>
{content}
</ScrollView>

之後

<Animated.ScrollView // <-- Use the Animated ScrollView wrapper
scrollEventThrottle={1} // <-- Use 1 here to make sure no events are ever missed
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.animatedValue } } }],
{ useNativeDriver: true } // <-- Add this
)}
>
{content}
</Animated.ScrollView>

注意事項

並非目前在 Native Animated 中支援您可以使用 Animated 執行的所有操作。主要限制是您只能動畫化非佈局屬性,transformopacity 等屬性將會起作用,但 Flexbox 和位置屬性則不會。另一個限制是 Animated.event,它僅適用於直接事件,而不適用於冒泡事件。這表示它不適用於 PanResponder,但適用於 ScrollView#onScroll 等。

Native Animated 也已成為 React Native 的一部分相當長一段時間,但從未記錄在案,因為它被認為是實驗性的。因此,如果您想要使用此功能,請確保您使用的是最新版本 (0.40+) 的 React Native。

資源

有關動畫的更多資訊,我建議觀看 Christopher Chedeau演講

如果您想深入了解動畫以及將動畫卸載到原生如何改善使用者體驗,還有 Krzysztof Magiera演講