天天看點

gasbuddy娛樂當地人的React React本機圖像生成器 (react-native-image-builder) React本機字元串 (react-native-strings) React導航代碼 (react-navigation-codegen) 陷阱(和解決方案) (Gotchas (and solutions))

重點(Top highlight)

I had to check Medium, because I felt like perhaps I wrote a draft of this story 15 months ago. That was the last time I thought “perhaps we should rebuild our app in React Native.” That lasted a few weeks as I made the shell of an app, discovered various roadblocks and got a sense for how hard the overall task would be. It did not reach activation energy then. There were many reasons for that, both from a maturity standpoint in React Native and the circumstances at GasBuddy. We still retained the majority of the team that built our native apps from the ground up more than a decade ago. Most of our iteration was backend heavy — we built a payment product that sold a half a billion dollars in fuel and we integrated telematics and vehicle recall notifications and such. Having to build the front end to those features twice (iOS+Android) and sometimes thrice (iOS+Android+Web) was annoying, but not prohibitive.

我不得不檢查中,因為我覺得也許15個月前我寫了這個故事的草稿。 那是我最後一次想到“也許我們應該在React Native中重建我們的應用程式”。 當我制作一個應用程式外殼時,這持續了幾個星期,發現了各種障礙,并對整體任務的艱辛感有所了解。 那時它沒有達到活化能。 出于多種原因,無論是從React Native的成熟度角度還是GasBuddy的情況來看。 十多年前,我們仍然保留了從頭開始建構本機應用程式的大多數團隊。 我們的大部分疊代工作都是在後端進行繁重的工作-我們開發了一種付款産品,該産品售出了十億美元的燃料,并且內建了遠端資訊處理和車輛召回通知等。 不得不兩次建構這些功能的前端(iOS + Android),有時又要建構三次(iOS + Android + Web),這很煩人,但并不是禁止的。

On the React Native side, there were several big blockers that made me less than excited about the long road to feature parity with the existing apps.

在React Native方面,有幾大阻礙因素使我對與現有應用程式實作同等功能的漫長道路感到不滿意。

  1. Navigation was messy. react-native-navigation seemed the most mature option, but it was incredibly finicky to get working, and as new version of React Native came out, even in the short months I spent dabbling, I had to do those finicky things all over again.

    導航很混亂。 react-native-navigation似乎是最成熟的選擇,但是它上班的難度令人難以置信,而且随着新版本的React Native的出現,即使在短短的幾個月裡,我也不得不重新做那些挑剔的事情。

  2. Image handling was daunting — SVG is clearly the right answer for source material, but it seemed to be poorly integrated into the workflow of RN apps. That may have just been my lack of understanding, but it was a concern for large scale development.

    圖像處理令人生畏— SVG顯然是擷取原始資料的正确答案,但似乎沒有很好地內建到RN應用程式的工作流程中。 那可能隻是我缺乏了解,但這是大規模開發的一個問題。

  3. Native modules were a complete pain. Anyone working with RN before automatic linking would likely agree that it was messy — modifying pod files, native code on both platforms, managing version clashes — it was just drudge work. 99% of that pain is just plain gone.

    本機子產品是一個完全的痛苦。 在自動連結之前使用RN的任何人都可能會認為它很雜亂—修改pod檔案,兩個平台上的本機代碼,管理版本沖突–隻是費力的工作。 那種痛苦的99%隻是消失了。

Additionally, it was about 6 months after the infamous AirBnB middle finger to React Native. I think the articles were quite balanced and honest, but every time someone wants to bash RN, these articles are point number 1. I feel that misses some key nuances. First, a great many of the problems AirBnB had have in fact been addressed. They were a victim of timing, and their loss and pain are the rest of the ecosystem’s gain. Second, GasBuddy is not AirBnB and if you’re at a technology company considering React Native, you probably aren’t either. Their native app teams are probably bigger than our entire company. Their app is known for leading edge design, animation and visual polish that is hard to achieve with anything between you and the hardware.

此外,在臭名昭著的AirBnB中指使用React Native大約6個月後。 我認為這些文章非常均衡和誠實,但是每次有人要抨擊RN時,這些文章都是第一點。我覺得這遺漏了一些關鍵的細微差别。 首先,AirBnB實際上已經解決了許多問題。 他們是時間的受害者,他們的損失和痛苦是生态系統獲得收益的其餘部分。 其次,GasBuddy不是AirBnB,如果您在考慮使用React Native的技術公司,那麼您可能也不是。 他們的本機應用程式團隊可能比我們整個公司都要大。 他們的應用程式以領先的設計,動畫和視覺修飾而聞名,而您與硬體之間的任何事情都很難實作。

So, fast forward 15 months and a variety of changes made me wonder whether it was time to take another look. I started out the same way as before, but with the learnings of the past I had some demands of the code:

是以,快進15個月以及各種變化使我想知道是否該該換個角度了。 我以與以前相同的方式開始,但是随着過去的學習,我對代碼有了一些要求:

  1. Monorepo. Because of the pain I had dealing with React Native version changes, I wanted as little code in the “app” as possible. This is of course a good Javascript discipline in general — small easily consumable modules. Javascript has infrastructure for exactly this scenario, via Lerna and yarn workspaces, but it is notoriously finicky with React Native. I wanted to solve this from the start.

    Monorepo。 由于我在處理React Native版本更改時遇到的痛苦,我希望在“應用程式”中盡可能少的代碼。 一般來說,這當然是一門好的Java學科-小型易耗子產品。 Javascript通過Lerna和yarn工作區為這種情況提供了基礎設施,但衆所周知,它與React Native的關系很複雜。 我想從一開始就解決這個問題。

  2. Death to Redux. I do not like Redux. I do not like repeating myself. I do not like strings as identifiers in code. I do not like four files for every single thing the app needs to do. In the React world, I prefer unstated. I initially expected to use unstated-next but eventually decided on mobx-state-tree even though it’s a little heavy handed.

    Redux之死。 我不喜歡Redux。 我不喜歡重複自己。 我不喜歡字元串作為代碼中的辨別符。 我不喜歡應用程式需要做的每件事的四個檔案。 在React世界中,我更喜歡unstated 。 我起初希望使用unstated -next,但最終決定使用mobx-state-tree,即使它有點笨拙。

  3. Typescript. This wasn’t a must have at the beginning, but people I respect had recently started a React Native project and used Typescript, so I figured we’d give it a try. In retrospect, it’s been instrumental in making a pleasant and fast developer experience, mostly because of its impact on Intellisense in Visual Studio Code. Getting some veil of type safety for free was a nice addition. This is another place where time has helped a great deal. The number of RN-related modules that have Typescript support now is significantly higher than what I recall from the last attempt.

    打字稿。 這不是一個必須的開頭,但人我尊重最近開始了一個陣營本地項目和使用的打字稿,是以我想我們會試試看。 回想起來,它對獲得愉快和快速的開發人員體驗很有幫助,主要是因為它對Visual Studio Code中的Intellisense有影響。 免費獲得一些類型安全的面紗是一個不錯的選擇。 這是時間幫助很大的另一個地方。 現在,具有Typescript支援的RN相關子產品的數量大大高于我上次嘗試的數量。

  4. react-navigation. It has matured a great deal over the year, performance appears on par with native navigation on modern devices, and there is no fuss. The declarative model seems a great fit for modern React and works smoothly with hooks and contexts and Storybook and all such things.

    React導航。 它在過去一年中已經非常成熟,其性能與現代裝置上的本機導航相當,并且沒有大驚小怪。 聲明性模型似乎非常适合現代React,并且可以與鈎子,上下文和Storybook等所有東西一起順利使用。

Perhaps as importantly, our circumstances have changed. We are focusing more on front end iterations like “search along route” and in-app personalized gas discounts and now spend a high percentage of our time building the same things twice. We are also just experimenting more often, trying to find the perfect copy or the best way to onboard casual app downloaders into GasBuddy members and users of our Pay with GasBuddy product. We’ve built a bunch of server side infrastructure to enable that experimentation, but honestly a bunch of it is just bending to the realities of upgrading mobile applications. Some of those original developers have also moved on to other opportunities, and as it was several of their first jobs in industry, I can’t really fault them for that.

也許同樣重要的是,我們的情況已經改變。 我們将更多的精力放在前端疊代上,例如“沿路線搜尋”和應用程式内個性化的汽油折扣,現在,我們花費了很大一部分時間來兩次建構相同的東西。 我們也隻是在做更多的嘗試,試圖找到完美的副本或将休閑應用程式下載下傳器引入GasBuddy會員和我們的Pay with GasBuddy産品使用者的最佳途徑。 我們已經建立了許多伺服器端基礎架構來支援該實驗,但是老實說,其中的一部分隻是針對更新移動應用程式的現實。 這些原始開發人員中的一些人還轉移到了其他機會上,由于這是他們在行業中的第一份工作,是以我不能對此感到真正的錯。

Of course all code eventually needs to die. We’ve made lots of changes — to Swift and Kotlin, to a new service layer, etc — but there is no denying that there are plenty of cobwebs in our codebase. Dark corners that everyone is afraid to touch or has no clue what they even do anymore. By the way, that turns out to be one of the biggest determinants of migration speed in React Native: our ability to find documentation or even descriptions of why certain things do what they do. How is login supposed to work when you use a Google sign in to an account for which you no longer have access to the email address? How does the current search persist as your location changes if you had been on some sort of search along a route? The list is endless and each of them takes nontrivial time to reverse engineer from the code. Often the two platforms don’t even take the same approach, and I suppose that’s no surprise since the code bases are entirely separate.

當然,所有代碼最終都将死掉。 我們進行了很多更改-對Swift和Kotlin進行了更改,對新的服務層進行了更改-但無可否認,我們的代碼庫中有很多蜘蛛網。 每個人都不敢觸摸的黑暗角落,或者甚至不知道他們現在做什麼。 順便說一下,事實證明,這是React Native遷移速度的最大決定因素之一:我們能夠找到文檔或什至描述某些事情為什麼要做的描述。 當您使用Google登入無法再使用其電子郵件位址的帳戶時,登入應該如何工作? 如果您沿路線進行過某種搜尋,目前搜尋如何随着位置的變化而持續存在? 清單是無止境的,并且每個人都花了很短的時間來對代碼進行反向工程。 通常這兩個平台甚至都不采用相同的方法,我想這并不奇怪,因為代碼庫是完全分開的。

As we began this second attempt at React Native, I felt it was important to have some experts available to guide us, and got a recommendation from a friend for Infinite Red. In addition to just extra horsepower that didn’t detract from the existing roadmap, they helped us avoid a great many pitfalls, while still allowing us to have our own opinions and explore some new ground for both of us. React Native has been a fast moving platform since inception, and experience is extremely valuable and best when loosely held, and they’ve done a very good job of balancing that in our case. We have made great use of a shared Slack channel, and I would argue that channel has been the most “irreplaceable” part of our engagement with Infinite Red. They’ve done a tremendous amount of “real work,” but in terms of figuring out whether React Native is a realistic option for GasBuddy, the thousands of random questions and explorations we’ve done in that channel have been much more valuable. I think it’s fair to say there are innumerable blind alleys left in a production high-visibility React Native development effort, and it is crucial do avoid those which have deep pits at the end.

當我們開始在React Native上進行第二次嘗試時,我感到很重要的是要有一些專家來指導我們,并從一位朋友那裡獲得了Infinite Red的推薦。 除了提供不超出現有路線圖的強大功能外,它們還幫助我們避免了很多陷阱,同時仍使我們有自己的見解并為我們倆開拓了新的天地。 自從成立以來,React Native一直是一個快速發展的平台,經驗極其寶貴,最好是在松散狀态下保持最佳狀态,在我們的案例中,他們做得很好,可以很好地平衡這一點。 我們充分利用了共享的Slack管道,我認為該管道是我們與Infinite Red合作最“不可替代”的部分。 他們已經做了大量的“實際工作”,但是就弄清React Native是否是GasBuddy的現實選擇而言,我們在該管道中完成的數千個随機問題和探索意義更大。 我認為可以公平地說,在生産高可見性的React Native開發工作中留下了無數的小巷,并且至關重要的是要避免最後出現深坑。

I made some big process decisions early that shaped our work in the first month.

我在第一個月就做出了一些重大的流程決策,這些決策影響了我們的工作。

  1. We were going to build from the ground up. We were not going to integrate some React Native screens into the existing app, even as a proof of concept. I believe many of the gains React Native may deliver will require not carrying the baggage of the existing apps.

    我們要從頭開始。 我們不打算将某些React Native螢幕內建到現有應用中,即使隻是作為概念證明。 我相信,React Native可能帶來的許多收益都将要求不承擔現有應用程式的負擔。

  2. We were going to replicate the existing app design as closely as possible. There are plenty of reasons to redesign our app, and you can argue that combining a redesign and a re-platform would be more efficient than doing them independently. Since we don’t have a completed redesign, I felt this just meant we would never finish the re-platforming. Our goals are around efficiency and flexibility, so the longer we delay sunsetting the existing apps, the longer we end up having to build each feature 3 times. Now, as a practical matter, if we know redesigns are coming to elements in the app long before we would be done with React Native, we will wait for those to be completed in the existing app before porting them to React Native. If and when we truly decide to go to React Native, I believe there will be redesigns that we choose to execute first on an unreleased React Native app, because we can user test more easily, perhaps even beta test more easily and flesh out all the non-mobile elements (supporting back end services, etc) ONCE on React Native and then just copy the design to the native apps without having to wait for any supporting changes.

    我們将盡可能地複制現有的應用程式設計。 有很多原因可以重新設計我們的應用程式,并且您可以辯稱,将重新設計和重新平台結合起來比獨立進行更有效。 由于我們還沒有完成重新設計,是以我覺得這意味着我們永遠不會完成重新平台設計。 我們的目标是圍繞效率和靈活性,是以延遲淘汰現有應用程式的時間越長,最終每次建構3次功能的時間就越長。 現在,實際上,如果我們知道重新設計要早于應用本機中的元素,那麼在将它們移植到React Native之前,我們将等待現有應用中的重新設計。 如果并且當我們真正決定使用React Native時,我相信将會有一些重新設計,我們選擇先在未釋出的React Native應用上執行,因為我們可以使使用者更容易地進行測試,甚至可以更容易地進行beta測試并充實所有非移動元素(支援後端服務等),隻需在React Native上執行一次操作,然後将設計複制到本機應用即可,而不必等待任何支援性更改。

Given those decisions, the Infinite Red developers and I set about building as much of the app as we could in a month. We made it pretty far — navigation, registration and login (simplified), service interfaces, state management, basic location management, gas station listings… All of these worked well enough to fool you into thinking they were done. They looked close to pixel equivalent to the native apps. They performed well enough. The code was maintainable, clear, and predictable. We had some basic tests, CI/CD, style guides, setup scripts… It was a real project. We decided it was time to share it with the broader teams.

鑒于這些決定,我和Infinite Red開發人員開始着手在一個月内建構盡可能多的應用程式。 我們已經走到了很遠–導航,注冊和登入(簡化),服務界面,狀态管理,基本位置管理,加油站清單……所有這些都運轉良好,足以使您以為自己已經完成。 它們看起來接近與本機應用程式等效的像素。 他們表現很好。 該代碼是可維護的,清晰的和可預測的。 我們進行了一些基本測試,CI / CD,樣式指南,設定腳本……這是一個真實的項目。 我們認為是時候與更廣泛的團隊分享它了。

The #1 thing that would kill React Native at GasBuddy would be our engineering team deciding it wasn’t worth the effort, or wasn’t the right long term decision. We made a pretty good demo with some elbow grease and experienced help from Infinite Red. The work we did was not throw away work — the code is a solid and real foundation for a full blown app. It would be naive to say, however, that we were 25% done, or even 10% done. So the idea that we could get to 100% without meaningful involvement from the existing team, not to mention the horrible position that would leave us in at the end, is wrong. It will likely take us 5–6 months with 4–5 resources at the least to have a fully working app. So we need coverage on the existing apps in that time, and we will need to reduce our overall output to accommodate direct and indirect work on the React Native app. It is eminently reasonable to think this is too high a price to pay, and even more so if you aren’t convinced of the benefits or the likelihood of success.

在GasBuddy殺死React Native的第一件事是我們的工程團隊認為這不值得付出努力,或者這不是正确的長期決定。 我們用了一些肘部潤滑脂做了一個很好的示範,并得到了Infinite Red的幫助。 我們所做的工作并不是放棄工作-代碼是功能完善的應用程式的堅實基礎。 然而,天真地說我們完成了25%,甚至完成了10%。 是以,我們可以在沒有現有團隊有意義參與的情況下達到100%的想法是錯誤的,更不用說最終會使我們陷入困境的可怕位置了。 擁有完全可用的應用程式,至少需要4-6個資源才能花費我們5-6個月。 是以,我們需要在那時覆寫現有應用程式,并且我們需要減少整體輸出以适應React Native應用程式上的直接和間接工作。 認為這是要付出的代價太高了,這是絕對合理的,如果您不相信收益或成功的可能性,則更是如此。

So we did a big demo, described the merits of React Native, and etc. In general I think it’s fair to say people were impressed at the progress in a short time with a few people. But our team pointed out a very obvious thing that hadn’t really occurred to me until then — they don’t even have time to EVALUATE whether React Native is a good idea or not. They’ve got 70 points to finish every sprint, and this would take a bunch of them. I imagine the response at most companies of our size would be the same. We decided that what might be most helpful is if we could all focus on React Native for some short period, and “React Native Week” was born. It took some time to convince the rest of the company that a 1 week “work freeze” was worth it. We came close to cancelling the whole damn thing. But we decided it was now or never.

是以,我們做了一個大型示範,描述了React Native的優點,等等。總的來說,我認為可以說,在短時間内與幾個人一起給人們留下了深刻的印象。 但是我們的團隊指出了直到那時我才真正想到的非常明顯的事情-他們甚至沒有時間評估React Native是否是一個好主意。 他們獲得70分才能完成每次沖刺,而這需要一堆。 我想我們這個規模的大多數公司的React都是一樣的。 我們認為最有用的是,如果我們都可以在短時間内專注于React Native,那麼“ React Native Week”就誕生了。 花了一些時間才能說服公司的其他成員,為期一周的“當機工作”是值得的。 我們幾乎要取消整個該死的事情。 但是我們認為現在或永遠不會。

I am finishing this article at the end of React Native Week. Before it started, we spent time cleaning up the React Native build process and simplifying code where possible, and we created dozens of github issues for simple changes that would be useful for novice React Native developers to take on. The first day we did a little “firehose” spraying covering the basics of modern Javascript, React, and tooling and we concluded the day making sure everyone had a build up and running. Day 2 was pretty quiet, and I was concerned maybe it wasn’t going well or that there wasn’t enough training to make sense of an already fairly large code base. By the end of the day, the pull requests starting coming in, and they were much better quality than I expected. They provided great opportunities to discuss approaches, highlight CI/CD deficiencies and talk about why some structural decisions were made.

我将在React Native Week結束時結束本文。 在開始之前,我們花時間清理了React Native的建構過程,并在可能的情況下簡化了代碼,并且我們建立了數十個github問題來進行簡單的更改,這些内容對于新手React Native開發人員來說非常有用。 第一天,我們進行了一些“ firehose”噴灑,覆寫了現代Javascript,React和工具的基礎,我們結束了這一天,以確定每個人都已建構并運作。 第2天非常安靜,我擔心也許進展不順利,或者沒有足夠的教育訓練來了解已經相當大的代碼庫。 到今天結束時,拉動請求開始出現,它們的品質比我預期的要好得多。 他們提供了很好的機會來讨論方法,強調CI / CD的不足以及談論為什麼要做出一些結構性決策。

I plan to keep updating this article as we make a final decision. If we choose to move to React Native, I plan for us to do it “in the open” as much as possible so perhaps our experiences help someone else. While I don’t think we are likely to open source the GasBuddy app, whatever modules that we can isolate that might be generally useful we will open source from the start. We’ve got 3 so far, hopefully of some use to someone!

在我們做出最終決定時,我計劃繼續更新本文。 如果我們選擇遷移到React Native,我計劃盡可能“公開”進行操作,是以我們的經驗也許會幫助其他人。 雖然我認為我們不太可能開源GasBuddy應用程式,但是我們可以隔離的子產品通常可能有用的任何東西,我們都将從一開始就開源。 到目前為止,我們有3個,希望對某人有用!

React本機圖像生成器 (react-native-image-builder)

We needed a workflow that accommodated SVG and PNG inputs and produced easily usable components. In the case of SVG, it needed to convert them to Typescript-safe components and for PNGs I’d prefer to store one image in the repo and generate the other resolutions automatically in the common cases. I did not find tooling that let us do all these things, so we wrote some. react-native-image-builder takes a directory of image files and produces typescript files and scaled PNGs in a way that can be built and consumed as a module in a monorepo.

我們需要一個能夠容納SVG和PNG輸入并産生易于使用的元件的工作流。 對于SVG,需要将它們轉換為Typescript安全的元件,對于PNG,我希望将一個圖像存儲在存儲庫中,并在通常情況下自動生成其他分辨率。 我沒有找到可以讓我們做所有這些事情的工具,是以我們寫了一些。 react-native-image-builder擷取圖像檔案目錄,并以可在monorepo中作為子產品進行建構和使用的方式生成打字稿檔案和縮放的PNG。

React本機字元串 (react-native-strings)

It’s been a long source of embarrassment that the GasBuddy app is only available in English. It is not purely a client side problem (not to mention marketing emails and the like), but it is predominantly one. We wanted a simple, typesafe mechanism for defining localized, templated strings. We decided on a yaml format and open sourced the react-native-strings module that converts templated string specifications into Typescript and then runtime values. We will also be extending this to allow runtime overrides of strings from the server, even though this is marginally useful once you have CodePush and dynamic updates of the whole bundle.

長期以來,GasBuddy應用程式僅以英語提供。 這不是純粹的用戶端問題(更不用說市場營銷電子郵件之類的問題了),但主要是一個問題。 我們需要一種簡單的類型安全機制來定義本地化的模闆化字元串。 我們決定使用Yaml格式,并開源了react-native-strings子產品,該子產品将模闆化的字元串規範轉換為Typescript,然後轉換為運作時值。 我們還将對此進行擴充,以允許伺服器上的字元串在運作時進行覆寫,即使您具有CodePush和整個捆綁包的動态更新後,此功能也将非常有用。

React導航代碼 (react-navigation-codegen)

The navigation stack of an app can get fairly complicated. Nested stacks and modals, tab navigators, top tabs… oh my. Each of the screens in this web has a name, and some have typed parameters. I found myself repeating the same strings and types multiple times for more complex scenarios and I didn’t like it. So you are probably detecting a theme from the previous two examples, and wedid the same — created an intermediate format where we specify the structure of the stacks, the parameters each screen takes and the names of the screens (with sensible defaults). The react-navigation-codegen module is part of the build script for a low level module (called infra in our case) and allows us to navigate to screens with full type safety and not have to write lots of painful type declarations or worry about complex cross-module dependencies on where these types and screen name values are defined.

應用程式的導航堆棧可能會變得相當複雜。 嵌套堆棧和模式,頁籤導航器,頂部頁籤……我的天哪。 該網絡中的每個螢幕都有一個名稱,有些螢幕具有鍵入的參數。 我發現自己在更複雜的場景中多次重複相同的字元串和類型,但我不喜歡它。 是以,您很可能從前兩個示例中檢測到一個主題,并進行了相同的操作-建立了一種中間格式,在該格式中,我們指定堆棧的結構,每個螢幕采用的參數以及螢幕名稱(明智的預設設定)。 react-navigation-codegen子產品是低級子產品(在我們的情況下稱為infra)的建構腳本的一部分,它使我們能夠導航到具有完整類型安全性的螢幕,而不必編寫許多痛苦的類型聲明或擔心複雜性跨子產品依賴性,這些類型和螢幕名稱值的定義位置。

陷阱(和解決方案) (Gotchas (and solutions))

For our setup, storybook and the app are separate “small” modules in the monorepo. We want to be able to simultaneously run the storybook bundler and the main app bundler, and thus have to set them to run on different ports. This turned out to be tricky to do cleanly. Running the bundler is easy, we modify package.json in the storybook app to be:

對于我們的設定,故事書和應用程式是monorepo中單獨的“小”子產品。 我們希望能夠同時運作Storybook捆綁程式和主應用程式捆綁程式,是以必須将它們設定為在不同的端口上運作。 事實證明,這樣做很棘手。 運作捆綁程式很容易,我們将故事書應用中的package.json修改為:

"start": "react-native start --port 8082",
           

But it proved to be much harder to modify the iOS project to default to this port. We had to modify the post-install step for our storybook Podfile with this at the end of the main target section:

但是事實證明,将iOS項目修改為預設為該端口要困難得多。 我們必須在主要目标部分的末尾修改此故事書Podfile的安裝後步驟:

post_install do |installer|
  flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    if target.name == "React-Core"
      target.build_configurations.each do |config|
        if config.name != 'Release'
          config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'RCT_METRO_PORT=8082']
        end
      end
    end
  end
end
           

That magic spell modifies the build config for the React-Core CocoaPod to set the default metro port. On Android, it was simpler once I knew where to put it. In gradle.properties in storybook/android, I added a single line:

該魔術咒語修改了React-Core CocoaPod的建構配置,以設定預設的城域端口。 在Android上,一旦我知道将其放置在哪裡,它就會變得更加簡單。 在storybook / android的gradle.properties中,我添加了一行:

reactNativeDevServerPort=8082
           
翻譯自: https://medium.com/swlh/gasbuddy-entertains-react-native-5f4daa535990