-
-
Notifications
You must be signed in to change notification settings - Fork 665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RN 60 upgrade #4133
RN 60 upgrade #4133
Conversation
Oops! I was just reminded by #4089 (comment) and the doc linked from there that we're sticking with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Glad this is now nearly complete.
In the main upgrade commit, would it be possible to make a more concise summary near the top of what changed and why? I'm imagining something like
* Upgrade react-native, react, and flow-bin following the templates.
* Upgrade react-native-sound, react-native-webview, and rn-fetch-blob
as required to satisfy peer-dependencies.
* Adapt our Podfile to RN v0.60's new layout of pods, following the templates;
details below.
* Update our yarn.lock and Podfile.lock by running `yarn`, and deduplicate
with `yarn yarn-deduplicate` as prompted by `tools/test deps`.
Ah, aha, as I read more I realize one correction to that: it'd be more like
...
* Upgrade react-native-webview to satisfy peer-dependencies.
* Adapt our Podfile to RN v0.60's new layout of pods, following the templates.
* Upgrade react-native-sound and rn-fetch-blob to versions with podspecs
compatible with the new pod layout in RN v0.60.
But perhaps that helps illustrate why a summary would be helpful 😉
Maybe also a bullet about how we ignore or have already handled changes to the Xcode and Gradle configs.
Then after the summary, can still go into detail on the more complex of these.
Otherwise this looks good through the upgrade and the FlowFixMe followup! Still reading the commits after that.
d8329e6 android build: Prepare to activate Hermes.Tiny nit, but I'd more typically say "enable Hermes" or "switch to Hermes".
I read this as saying this part (this commit?) corresponds to the first two of these. But I think it corresponds to all of them together? I think squashing it like this probably is indeed the cleanest way to show it. We can probably also tell the story more simply to match -- like just list the four commits and say it's the combination of them. |
Ah, right, thanks for catching that! I think I meant "this part" as "they
and "Then:" referred to the second part (and didn't characterize that second part at all; I should fix that). I agree it's ambiguous; I'll find a way to clear that up. |
Thanks for your comments so far! They're all very helpful; I'll address them tomorrow. I wasn't sure if it was possible to adequately summarize all the information but clearly you've gotten most of the way there, so I'll take it from there! 😄 |
Ah, haha. I think the variable they use in the template is indeed Now I have some monstrosity in my mind about a mad scientist in some sci-fi comic evilly commanding "Activate Hermes!" and Percy Weasley's owl Hermes shoots out from somewhere and squawks. |
I remembered that we need a libdef for |
Updated this wth the I believe I've also addressed your other comments, but let me know if the summaries / rewordings could be improved, of course. 🙂 |
Very helpful, thanks! 2db86bb Upgrade React Native from v0.59 to v0.60.
|
747145f libdefs: Compose and use libdef for
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And done reading the rest of the branch. Thanks again!
(More-substantive comments above.)
// Add unimodules | ||
List<ReactPackage> unimodules = Arrays.<ReactPackage>asList( | ||
new ModuleRegistryAdapter(mModuleRegistryProvider) | ||
); | ||
packages.addAll(unimodules); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this different from just packages.add(new ModuleRegistryAdapter(…))
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, interesting! I don't know what else might be supposed to go in this list, eventually. I was following this: https://gist.github.com/mczernek/9de9e184abc430e9e3508d26738c8a14/revisions
which is linked to from https://github.com/unimodules/react-native-unimodules, as "this diff for react-native >= 0.60".
I think it makes sense to just do packages.add(new ModuleRegistryAdapter(…))
.
android/app/build.gradle
Outdated
@@ -239,3 +267,6 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { | |||
jvmTarget = "1.8" | |||
} | |||
} | |||
|
|||
// Necessary for Autolinking; see facebook/react-native@261197d85 | |||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: newline at end of line
Also, let's uncramp this line by putting the statements on separate lines. I can see why people jam them into one line when writing instructions and saying to copy-paste; but now that it's part of our source code, it's better to put the code in a reasonable format.
android/settings.gradle
Outdated
@@ -1,33 +1,7 @@ | |||
rootProject.name = 'ZulipMobile' | |||
|
|||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similarly, let's uncramp this onto two lines
Also the blank lines seem helpful, separating logical stanzas of related code.
Thanks for the detailed review! I'll respond in chat, starting here. |
436c3a3
to
8b3c1aa
Compare
c1b2f46
to
3cef08b
Compare
I think you're still working on the r-n-webview libdefs. On the rest, just small comments:
This isn't entirely right -- the abstract class I think just saying "the one returned by the
Why the backticks around the commit ID? Without them, the GitHub view of the commit message will linkify it, which seems useful. Otherwise all looks good! |
Ah OK, good to know, thanks! I wasn't aware of anonymous classes. |
Habit, I think — using backticks means something is definitely not an English word. But...this is already definitely not an English word! And those links are helpful. GitHub will autolink (ha) to the commit from the facebook/react-native repo, but that's fine. |
Thanks for the review! I've pushed the changes with the |
Great! This all looks good -- just a couple of small nits. The PR is marked as draft; is there a reason that's intentional or did you mean to lift that? 320ab3a Upgrade React Native from v0.59 to v0.60.
nit: The "Foo: something" metadata lines at the end go together as one stanza; see for example the commit messages in linux.git. For a specific example, here's the latest non-merge commit at the moment in Linus's tree: torvalds/linux@db33ec3 37cbe11 libdefs: Compose and use libdef for
|
Mmm, thanks for catching this! Also, I don't remember why I put the In fact, it looks like the actual line (line 378) is this:
Not really something we've made a pattern of doing in our code, but maybe I'll use this just for consistency. |
and I just un-marked it as a draft! Yeah, I should have done that earlier. |
This will be necessary when we move to a custom, better libdef for `react-native-webview` in the RN v0.59 -> v0.60 upgrade.
`react-native-vector-icons` gives two options for setup on Android [1]: - Option: With Gradle (recommended) - Option: Manually When we first installed it in e5cbe3c, we...mostly went with the latter (which is also "with Gradle": it means including the library's Gradle project!), but we didn't follow through with an important edit to `MainApplication.java` as part of that option, or a (silly, as Greg points out [2]) move of some font assets into our source tree. In cd899bb, we accomplished the "With Gradle (recommended)" option. This seems better; we've never needed to do the things described as possible only with the "Manual" setup. But we didn't back out the then-unnecessary code from the "Manual" setup. So, do that now. Greg points out [2] that they're making the Gradle setup a lot more complicated than it really neads to be. [1]: https://github.com/oblador/react-native-vector-icons/tree/v6.6.0#android [2]: https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/RN.20autolinking/near/894795
This lets us insert fixmes in a separate commit from the upgrade that makes them necessary. Like we did in c542823.
When we upgrade Flow to v0.98 in tandem with RN to v0.60, we'll start getting errors here. Add fixmes for them.
Any later (7.0.0 or above), and we'd see peer dependency warnings about React Native. We'll upgrade to the latest 7.x in the same commit as the upcoming RN v0.60 upgrade. AndroidX support is the one declared breaking change [1] for version 6.x.x. We started using AndroidX in e433197; if we hadn't, we wouldn't be able to take this version. Also update the libdef; FlowTyped conveniently has one for version 6 (but no later): ``` flow-typed install react-native-webview@6 ``` [1]: https://github.com/react-native-community/react-native-webview#versioning
To reduce the size of the upcoming RN v0.60 upgrade. There, we will upgrade to the latest 7.x of `react-native-webview`. There isn't an off-the-shelf libdef from FlowTyped for 7.x, so we compose our own. That addition is pushed out of the main RN upgrade commit, just like this one, to reduce the size of the RN upgrade commit.
Using the RN Upgrade Helper, a web app showing the diff from the release/0.59.10 and the release/0.60.6 branches of the `react-native-community/rn-diff-purge` repo, at https://react-native-community.github.io/upgrade-helper/?from=0.59.10&to=0.60.6. In this commit: - Upgrade `react-native`, `react`, and `flow-bin` following the templates - Upgrade `react-native-webview` to satisfy peer dependencies - Adapt our Podfile to RN v0.60's new layout of pods, following the templates - Upgrade `react-native-sound` and `rn-fetch-blob` to versions with podspecs compatible with the new pod layout in RN v0.60 We've already done a lot of the work toward the upgrade, and we've ignored some changes suggested by the upgrade helper. See comments on zulip#3548. Note: The following warning appears when running Metro and will be fixed with follow-up work (e.g., zulip#4118): ``` warn The following packages use deprecated "rnpm" config that will stop working from next release: - react-native-orientation: https://github.com/yamill/react-native-orientation#readme - rn-fetch-blob: https://npmjs.com/package/rn-fetch-blob ``` ----- Platform-agnostic -------------------------------------------- We upgrade `react-native-webview` in this commit because versions before 7.x aren't compatible with RN v0.60, and versions 7.x aren't compatible with RN v0.59 (judging by peer dependency warnings). We take the latest 7.x version, 7.6.0. Nicely, this gets us the changes from one of our PRs, released in 7.0.3; see 1982f3f and its reversion in the commit that followed, bbfac73. There's just one declared breaking change [1] in 7.x.x: - UIWebView removed (7.0.1). This prompted the `scalesPageToFit` prop to be removed, but we don't use it. The `useWebKit` prop was also removed because it doesn't make sense for it to be anything but `true` now. So, remove our use of it. Also run `yarn yarn-deduplicate && yarn`, as prompted by `tools/test deps`. [1]: https://github.com/react-native-community/react-native-webview#versioning ----- Android ------------------------------------------------------ There are no updates on the Android side that must happen atomically with the RN upgrade. ----- iOS ---------------------------------------------------------- facebook/react-native@2321b3fd7 appears to be the only cause of iOS changes that must happen atomically with the RN v0.60 upgrade. In that commit, all the "subspecs" that were nested under the "React" pod are un-nested so they each become their own pod, with many of these living in their own directory under node_modules/react-native/Libraries [1]. In our own code, this means changing our Podfile to refer to all these new pods, instead of the "React" pod's subspecs. So, do. Our Podfile has a list of "Pods we need that depend on React Native". We must also be sure all the dependencies in this list adapt to facebook/react-native@2321b3fd7. The syntax for pointing explicitly to a subspec is a slash, as in "React/Core" [2]. Knowing this, we check that list for pods that explicitly depended on those subspecs, with "React/[...]": ``` grep -Rl dependency.*React/ --include=\*.podspec \ --exclude="node_modules/react-native/*" node_modules ``` There are two, and they both have new versions that adapt to the new accepted shape: - `zmxv/react-native-sound@2f2c25a69`: "React/Core" -> "React" - `joltup/rn-fetch-blob`, `01f10cb10^..0f6c3e3cc`: "React/Core" -> "React-Core" So, take these new versions, and job done. [1]: They do still live in node_modules. It's possible for pods to be hosted online and downloaded on `pod install`, npm-style. For an example, see the 'Toast' dependency in node_modules/react-native-simple-toast/react-native-simple-toast.podspec. But that's not what's happening here, yet. facebook/react-native@2321b3fd7 hints that this will be the way of the future for React Native, "to make the experience nicer for library consumers". [2]: https://guides.cocoapods.org/syntax/podspec.html#subspec Fixes: zulip#3548 Fixes: zulip#4093
The latest version FlowTyped has a libdef for is 6, unfortunately. Ah, well. This is a best effort at replicating the types at react-native-webview/react-native-webview@c4001338c, tagged as v7.6.0, the latest 7.x. An improvement over the FlowTyped libdef is that WebView's props are now exact. So, e.g., people will be warned not to use the `useWebKit` prop, which was removed in 7.0.0. We found it impractical to correctly express the fact that the `WebView` component also accepts all the props that the `View` component does. Certainly it seems impossible to do so by importing things from React Native [1]. So, a partial reimplementation that allows a `style` prop (typed as an inexact object). See the entry in `docs/howto/libdefs.md` added in this commit for more detail. [1]: zulip#3458 (comment)
The only declared breaking change [1] is the following: """ onNavigationStateChange now triggers with hash url changes """ We haven't been using that prop, so this is fine. (Even if we were...I guess that could be a breaking change?) Inspecting any changed TypeScript files in a local clone of `react-native-webview`, between versions 7.6.0 and 8.0.4, suggests that we don't have to make any changes to the libdef: ``` $ git diff v7.6.0..v8.0.4 -- *.ts ``` (No results.) We'd like to go to the latest (10.2.3, currently), but react-native-webview/react-native-webview@bf1d64571, released in v8.0.5 [2], bumps the `react` peer dependency to ^16.9. We're using `react` at 16.8.6, since `react-native` 0.60.6 has `react` as a peer dependency on 16.8.6 exactly; this gets bumped in facebook/react-native@0ccedf396, released in v0.61.0. So, effectively, this means `react-native-webview` v8.0.5 bumps the React Native requirement to v0.61. Seems surprising that they didn't mention that, but, oh well. [1] https://github.com/react-native-community/react-native-webview#versioning [2] https://github.com/react-native-community/react-native-webview/releases/tag/v8.0.5
This also lets us re-enable failing on unused fixmes.
See zulip#4131, the issue for enabling Hermes. Part of the RN v0.59 -> v0.60 upgrade [1]. This must happen at or after the upgrade commit because the use of Hermes is newly supported. RN did this in two main steps that affected the template app, which we squash together in this commit. RN's first step was to start using NPM to manage the JSC version; this was released in v0.60.0: - facebook/react-native@8e375850d - facebook/react-native@4bb0b4f20 (a partial reversion) RN's second step was a large amount of setup to get Hermes ready, released in v0.60.1: - facebook/react-native@e857d7066 - Then facebook/react-native@0738fe573 fixed a small bug, released in v0.60.2. All four of the above-mentioned commits are reflected in this commit. [1]: https://react-native-community.github.io/upgrade-helper/?from=0.59.10&to=0.60.6
Part of the RN v0.59 -> v0.60 upgrade [1]. (Or, at least, RN and most library maintainers assume it is done as such.) This must happen at or after the upgrade because autolinking is a new feature. "Autolinking" [2] aims to make the "react-native link" command unnecessary, so that when we add a module with native code, all we have to do for the module to be included is run `yarn add`. (Other native-code changes, such as calling functions that the module provides, may still be necessary.) So, for Android: 1. As indicated in the doc [2], unlink everything from Android. As done in rk-for-zulip/zulip-mobile@6b50b1521, we do this with a script, but here, we tell `react-native unlink` to only unlink from Android. To be as exhaustive as possible, we tell it to unlink *all dependencies* in our package.json. Thankfully, if one isn't already linked, unlinking it is a no-op: ``` for dep in `tools/deps`; do react-native unlink --platforms=android "$dep" done ``` As in rk-for-zulip/zulip-mobile@6b50b1521, it looks like a custom script in Sentry removed some setup that we want to remain intact. So, exclude these from the commit: - In `ios/ZulipMobile.xcodeproj/project.pbxproj`, removing the "Upload Debug Symbols to Sentry" PBXShellScriptBuildPhase. We don't want to touch the iOS side at all right now. - In `android/app/build.gradle`, the removal of the line: ``` apply from: "../../node_modules/@sentry/react-native/sentry.gradle" ``` Strangely, `react-native unlink`'s changes in MainApplication.java did not touch the list returned by `getPackages`, but it did remove the imports that many of these list items depend on. So, remove these list items, taking note, for a future step, that a few are left intact: - `new MainReactPackage()` - `new ZulipNativePackage()` - `new NotificationsPackage()` - `new SharingPackage()` 2. Apply the Android-side changes from facebook/react-native@261197d85. In `getPackages`, this removes `MainReactPackage` and gives a new form to put the references to `ZulipNativePackage`, `NotificationsPackage`, and `SharingPackage`. 3. Now, go back to `react-native-unimodules` [3] and follow the "react-native >= 0.60" branch of the "Configure Android" instructions. We had to make some trivial changes in `MainApplication.java`; we push to the list at the now-existing `packages` variable instead of changing the literal list that was previously returned without being stored in a variable. 4. Add a `react-native.config.js` file, as the recommended way [2] to say we don't want certain modules to be linked. For details on `react-native-vector-icons`, see a commit earlier in this series that solidified our choice not to link `VectorIconsPackage`. 5. To compare the list of linked packages before and after this commit, note that in both cases, the list to be observed is the one returned by the `getPackages` implementation in `MainApplication.java`. Autolinking introduces an auto-generated `PackageList` class in `android/app/build/generated/rncli/src/main/java/com/facebook/react/PackageList.java` with a `getPackages` method of its own, which helps compose that list of packages we're observing. The `getPackages` implementation is auto-generated when you build for Android. So, compare (by alphebetizing and diffing) the list before autolinking with the new list put together with help from that auto-generated code. They are the same, so, job done. [1]: https://react-native-community.github.io/upgrade-helper/?from=0.59.10&to=0.60.6 [2]: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md [3]: https://github.com/unimodules/react-native-unimodules
Part of the RN v0.59 -> v0.60 upgrade [1]. (Or, at least, RN and most library maintainers assume it is done as such.) This must happen at or after the upgrade commit because autolinking is a new feature. Just like the previous commit, but for iOS. 1. Following the doc [2] as before, unlink everything. Again, with a script, but this time, only for iOS: ``` for dep in `tools/deps`; do react-native unlink --platforms=ios "$dep" done ``` Exclude the same set of Sentry changes as we did in this step for Android. Also, exclude a change to our Info.plist that would remove the "Fonts provided by application", a.k.a., `UIAppFonts`. This is a setup step [3] that we need to keep. So, we're left with the removal of all items from the "Pods we need that depend on React Native" list. Additionally, remove "libz" from our Xcode config. It was put there by Sentry, as a consequence of running `react-native link` before we were using CocoaPods. But Sentry expresses the same dependency in `Sentry.podspec`. So, having it in our Xcode config is redundant. [4] 2. Make the change recommended by facebook/react-native@86a97e783: import and call a method, `use_native_modules!`. 3. Now, go back to `react-native-unimodules` and follow the ">= 0.60" branch of the "Configure iOS" instructions. Turns out that no changes are needed here; the differences in expressing our React pod dependencies were handled in the main RN v0.60 upgrade commit. 4. Move the two deps under "RN-dependent Pods that we could include, but we've decided not to" into the `react-native.config.js`. 5. Add a workaround in `tools/postinstall` for an issue [5] with running `pod install` from the root directory with `--project-directory=ios`. We tried the workaround suggested in that issue, where we have `use_native_modules!(".")` in the Podfile and still call `pod install --project-directory=ios` from the root directory. (This might have led to a cleaner solution, where we pass "." in the postinstall case, and pass nothing otherwise.) But we got this error, which isn't addressed in that issue, and doesn't seem easy to fix without changes to `native_modules.rb`: ``` [!] No podspec found for `RNCAsyncStorage` in `./node_modules/@react-native-community/async-storage` ``` It's plausible that those investigating this issue were only testing with a template project that didn't have RN-dependent pods like RNCAsyncStorage, so, never saw this error. 6. Run `pod install` and see that the only change to `ios/Podfile.lock` is in the checksum. So, job done. [1]: https://react-native-community.github.io/upgrade-helper/?from=0.59.10&to=0.60.6 [2]: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md [3]: https://github.com/oblador/react-native-vector-icons#option-manually [4]: There's some uncertainty here; we're not seeing `z` or `libz` in ios/Pods/Pods.xcodeproj/project.pbxproj after running `pod install`, with or without autolinking. But it seems to work. More discussion at zulip#4026 (comment) and https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/RN.20autolinking/near/884333. [5]: react-native-community/cli#657 Fixes: zulip#4026
OK -- merged! 🎊 This was a big upgrade -- glad it's now complete. 😄 |
Closes #3548, #4026. Yay!
In this revision, there are two
prettier [nfc]
commits that are fine to merge first; just those two are at #4132.I ran
rm -rf node_modules; rm -rf ios/Pods; yarn; tools/test --full
at every commit, and they all passed. I opened the app on my iOS device and on the Android emulator (the Android devices has been having "Could not connect to development server" errors), poked around, sent a message, etc.; it all seems to work.There's just a bit of follow-up work to do, but I'll put that in its own PR so I don't crowd this one.