天天看點

[譯] 一名 iOS 開發者的 React Native 開發經曆一名 iOS 開發者的 React Native 開發經曆

<b>本文講的是[譯] 一名 iOS 開發者的 React Native 開發經曆,</b>

<b></b>

如果你是一名 iOS 開發者,你應該聽說過 React Native。它給出了簡單而吸引人的承諾:一次編寫,兩處部署,同時搞定 iOS 與安卓版本的 app。我是一名資深的 iOS 開發者(還是一名更資深的 macOS 開發者),我想分享我應用這門神奇技術的經曆。

去年,我們和一個客戶進行過交談。他們來找我們是因為他們想盡快完成他們的 iOS app。在讨論的過程中,他們提到了這個叫做 React Native 的東西。他們有個善于使用 Javascript 的 web 開發人員,那個人指出使用 RN 可以讓開發速度快很多。這場談判最終我們沒有達成共識而是以失敗告終,但這件事也讓我開始思考是否應該将 RN 納入我們的技術棧中

幾周後一位老友來訪,讓我為他出版的一本書制作一個 app 作為補充參考資料。因為這個工作我找到了一線機會:這是一個很棒的時機來試一試 React Native。由于他的讀者大多數使用安卓系統,是以「一次編寫,兩處部署」的理念在此深得我心。

我不會帶你親曆一遍我的各種嘗試和遇到的問題。但我要說的是,就這麼一個簡單的 app,并不能使用 RN 很好的進行開發。以下是原因。

首先,我必須說一下除開「一次編寫,兩處部署」的承諾,我喜歡 React Native 的地方。

React.js,RN 由它而生。它是一種描述與更新 UI 的優雅方法。它的基本原理是元件使用一組傳遞給它的屬性由上到下渲染其 UI。感謝 React 的虛拟 DOM,當屬性變化時 UI 會立即更新,使得 model 與 view 能夠自動且無縫地同步。我多麼希望 iOS 的 UIKit 也這樣設計啊!

更新 JSX 代碼就可以在模拟器中更新 app 而不需要重新編譯與重新運作,這點真的很棒。

蓬勃發展的 RN 社群提供了數以百計的預制元件,你可以在你的 app 中使用它們。(實際上我非常讨厭這種看似專業的「腳本小子」的程式設計方法。建構一個大部分都不是你自己寫的,并且弄不明白的 app,将會導緻之後的維護如同陷入泥潭一般困難)

我很擔心 RN 的性能,但是在我的經曆中它并沒有出現問題。滾動和動畫都很流暢。畢竟 RN app 大部分使用的是平台原生的 UI 控件,RN 的工程師們也對它們進行了很好的優化。

那麼為什麼我不喜歡它呢?老實說,我并不是 React Native 的目标使用者。我熟悉 Javascript 但我并不精通它,我精通的是 Swift/Objective-C。我很快就意識到,如果我使用 RN 來完成這個 app,将會比我用 Swift 慢 10-20 倍。當然,安卓版本還要單獨寫,但是考慮到我學習 RN 的學習曲線,我還不如去學習 Java。

除此之外,我認為采用 RN 的解決方案還有一些嚴重的問題。

React Native 并不是一個一站式解決方案。我制作了一個粗略的必要元件依賴圖:

上圖為React Native 的依賴鍊

如果你來自 web 開發的世界,這可能對你來說很正常;但是對我來說,這很不正常。我的世界中有 Xcode,任何建立 Swift/Obj-C/iOS/Mac/Apple TV 等 app 所需要的東西都已經封裝好并由 Xcode 管理。依賴鍊和前面的圖一樣(甚至更長),但是依賴鍊中的東西都保證是同步且相容的。

我現在肯定 RN 依賴鍊中的大多數元件都是互相相容的。但我遇到了四五個需要在 StackOverflow 上花幾小時尋求解決方案的問題。在我心中更重要的是之後會發生的事情。例如,更新 Nuclide(IDE 的 RN 拓展)可能需要新版的 Atom。我系統中的另一個工具需要新版的 <code>winston</code>,如果那個版本不相容 RN 怎麼辦?後果可想而知。

事實證明「一次編寫,兩處部署」的承諾隻有部分實作了。我遇到了必須要把我的 RN app 根據目标平台(iOS 或安卓)進行「分支」的問題。例如 tab bar,你可能認為像它這麼随處可見的元件會被 RN 列為「一等公民」,但事實不是這樣的。RN 為 iOS 收錄了 <code>TabBarIOS</code>元件,但是因為某些原因它在安卓上并不相同。相反,在 GitHub 上有一堆的教程和解決方案教你如何從頭做起。又例如 nav bar,iOS 的 <code>NavigatorIOS</code> 與安卓的 <code>Navigator</code> 工作方式差别巨大。這些核心的導航功能結構在兩個平台上的差異會導緻要為每個平台分别編寫大量的不同的檔案與元件。我開始感覺到,盡管承諾很神奇,盡管我在用同一種語言,但其實我仍然在寫兩個不同的 app。

實際上,這個「承諾」其實是别人推斷的,并不是官方宣稱的(至少 Facebook/RN 的人沒有這麼宣稱過)。官方宣傳的是「一次學習,随處編寫」。

我在做的這個項目其實是一個層級化的參考指南。書作者和我為目錄與文章用我們設計的 UI 範式規劃了一套挺合理的布局。根據我們的想法,我們可以通過連結或導航跳轉到數百個使用靜态内容的詳情頁中。我寫好了代碼,但奇怪的是我調用 <code>require()</code> 一直不成功。我經過一段時間的研究,了解到 RN 限制您無法從任意路徑讀取檔案。顯然你的 RN app 在編譯時收集了所有可能用到的路徑,任何編譯器無法找到的路徑都将不能讀取。是以你可以用<code>require(‘../file1.json’)</code> 但不能用 <code>require(‘../file’ + ‘1’ + ‘.json’)</code>。這個讓人驚訝的限制使得我們的架構無法實作。

你最終完成的 RN app 可能既不像原生的 iOS app 也不像原生的安卓 app。大多數使用者可能不會察覺這個問題,但有些人會發現更大的問題。你有可能會丢失一些使用者會注意到的平台特有的細節,例如不能從左側右滑來傳回。(當你用 <code>NavigatorIOS</code> 完成兩個平台的導航時會出現這個問題)

總而言之,iOS 開發者不應該将 React Native 視為兩個平台的跨平台解決方案。寫一個原生的 iOS app 将會花費更少的時間并可能得到更棒的 UX。對于安卓 app 也一樣,是以我認為大家應該更多的去專注于平台原生解決方案。

什麼時候用 RN 才是正确的呢?如果你是一個專業的 Javascript 程式員或者你有這麼一個員工,并且你不打算配置 iOS 開發或安卓開發人員,那麼你可能會從中獲益。還記得那個想要盡快做好跨平台 app 的那個客戶嗎?他們曾有一名 Javascript 工程師,他們 app 的 v1.0 版本最近才出現在應用商店中。此時,距他們聯系我們已經過去了 8 個月。

<b>原文釋出時間為:2017年4月01日</b>

<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>

繼續閱讀