Bringing the New React Native Architecture to the OSS Community - Fall Edition

Bookmark

At the end of 2021, we successfully rolled out the New React Native Architecture in the Facebook app. Now, it’s time to empower every React Native developer on the globe to use the New React Native Architecture, both the new Fabric renderer and the new TurboModule system. But migrating an entire ecosystem to a New Architecture is no easy task. To support the whole community in this endeavor, we lined up a set of tools and materials that will help both app and library developers to join us in this journey. In the talk, we will present how the New React Native Architecture looks in the OSS space. We will discuss the impact this will have on developing React Native projects. Lastly, we will cover what we learned from the React Native New Architecture migration at Meta, and how you can tackle your migration in your organization.

by



Transcription


Awesome. So, hi everyone. Thank you very much for joining me today. We're going to talk about the new react Native architecture and how we bring it to the open source community. And as I believe a lot of you here might be react and not react Native developer, I hope you heard about react 18. So, to make it simple for you, the new architecture is how we're going to bring react 18 to mobile and to native. One of the things I like about myself, I'm actually an Android engineer working in the react Native team. You can find me online as Kurtinico on Twitter and on GitHub. And so, the new architecture of react Native has been in the media for quite some time. If you actually go online and search for react Native new architecture, you can find quite some content, I would say. And let's look through some of the videos that you will be seeing. The first one, it's from react Conf 2018. So, well, we've been talking so long about it. Like last year, my colleague Joshua gave a talk about it at react Native U and it was all about the new architecture within meta. But now the point is, okay, so we did our rollout internally. How do we bring it out? How do we let the open source community use it as well? So, if we look at a timeline of the new architecture, again, it was started as a six-month project in 2018. But it turns out that the biggest product that we have at meta that uses react Native, which is the Facebook app, is quite complicated. And trust me, engineers managed to use every possible edge case and every possible api of react Native to squeeze every performance out of this framework. So, it took us, at the end of the day, nearly three years to do the full rollout of the new architecture on the Facebook app. But then from there, as I said, we looked at ourselves and we asked, okay, how do we roll this out in the open source? And so, this talk is going to be about this exactly. Like how do we let people outside of meta benefit from react 18 and the new architecture on native? So, to do again one step back and really understand why we are bringing the new architecture, as I said before, we want to bring all the benefits of react 18 to native. But it's not only that. If you have been doing react Native, you probably know that there is this component which is sort of crucial in the react Native architecture, which is called the bridge. It's essentially a component where it allows the javascript layer to communicate with the native layer and everything is passed through this bridge as JSON. And as you can imagine, it's a huge bottleneck. So, first, we wanted to get rid of it. As we wrote a lot of the internals of our architecture, we actually took a stance and wrote them once. Like we used to have an Android renderer and an iOS renderer, which were not exactly aligned. So, we wrote a lot of the internals in C++ and this allowed us to share some platform specific optimizations between the two platforms. On top of that, using the bridge meant that we could not really benefit from type safety. That's why the new architecture has a new component called the code gen, which brings type safety inside our api. And finally, you should think of the new architecture as the foundational stone for a lot of features that will be built on top of react 18 and these new APIs and will be delivered also to native. So, we need to make sure that people are using those APIs. So, what are the core concepts of the new architecture? We call them pillars. And we have several of them. First, we have the new renderer. And this is what actually uses react 18. And this new renderer is often referenced as fabric. Then we have the new native module system, which allows you to interact with the native platform and call APIs of Android and iOS. And we call this mechanism turbo modules. Then, as I said before, we wanted to bring type safety in our formula. That's why we introduced a new component called the code gen. And the last pillar is bridge-less mode. So, once everything is in place, you have all of your components compatible with fabric and everything compatible with turbo modules and so on, you can fully turn off the bridge. So, I don't have the time, sadly, to deep dive in those. And they're also highly technical. But I want to give you a glimpse of how the code will look like as you start writing native modules and components and use the code gen. What we envision is that we want developers to define a spec. So, you will have like a typescript file, which looks more or less like this one. Here you define an interface and you say that you have a function which answers the ultimate question. And you register this module. And again, the point is this function and this signature. The code gen is able to understand that you are declaring like a public api that you will use on your javascript word. And the important information here is that there is an input, which is a string, and an output, which is a number. From this information, we can generate a lot of boilerplate code that you don't have to write. The thing is that web developers that work with react Native don't really like to write Android and iOS code. So, we're trying to make this as simple as possible. So, how this will look like on Android, we are going to generate some Java classes. So, we'll have like an abstract class with the constructor and a method that respects the signature. So, in this case, this would be an abstract method that accepts a Java string in input and returns a double. So, we do all the type, like we resolve the types to the platform specific types that every platform accepts. So, on iOS, for example, you're going to have Objective C protocol that accepts an S string and returns an NS number. Obviously, at some point you need to write the business logic. Like someone should answer the ultimate question. We can't answer that for you. But yeah, we're trying to simplify like a lot of boilerplate code that is not needed to be written anymore. Okay. So, yeah, like this new architecture required us to do a lot of changes across the board, as you can imagine, because now there is a code gen to run and there is, yeah, a lot of moving parts. So, we took a stance at our build tools. So, a lot of changes are actually coming on our integration with the underlying platform. And here there is a little bit of a challenge, because at Meta internally we use a build tool which is called Buck, which is also open source. And the new architecture for us internally works on top of this, which is great. But we can't expect people outside of Meta to use Buck, because it's open source. But we want to use the build tools which are specific to the platform you run on. So, on Android, you will run on Gradle. And we took a lot of time to sort of make sure that everything integrates well. There will be some C++ code. So there will be also CMake files that are handled by Gradle. Little disclaimer, a lot of people told me I don't want to see C++ code. So, we sort of encapsulated everything. Like web developers will not have to see CMake or C++ code at all, but it's under the hood and can be used for performance specific applications. We wrote our Gradle plugin. And ideally this is going to like effectively actually in react Native 71, this removes a lot of the legacy code and a lot of the build failures users were experiencing when creating your Android app. This logic has been completely rewritten. So the TLDR here is that within your architecture we're actually cleaning up a lot of the, let's say, legacy code, the legacy build infrastructure which built up on our open source code during the years. On iOS, similarly, we do have Cocoa Pods. And again, we took the stance here to clean up things a bit. We wrote a lot of the logic. Now we have like a full suite of Ruby scripts which are easier to use. They're smaller and they're fully tested. So hopefully you will see less build failures in the future. Okay. So another component that we actually, it's not necessarily part of the new architecture, but we spend a lot of time on it and we envision the new architecture with these things bundled together is our javascript engine called Hermes. So in the documentation for the new architecture, you will actually find it recommended and we can provide better support. Like if your app is crashing and you have Hermes, we can know more what's going on. So we invite users to use this engine and raise any issues you might have. From react Native 69, we actually did a change which is called bundled Hermes. So every version of react Native now comes with a specific version of this javascript engine, which we know being fully compatible with the version of react Native. In the past, we had scenarios where the engine was built at a given time and react Native was built at another time and they were not really compatible each other. So now you have an engine which is fully compatible with your version of react Native every time and you can just use it. From react Native 70, which we released a couple of months ago, Hermes is actually the default engine. So all the new project will have Hermes enabled by default. And if you don't want it because you might have a valid reason, you will need to disable it. A couple of updates also that we did on the modern languages side of things. Like a lot of people ask us to use different programming languages when they use react Native. And here I have a lot of updates actually. typescript. When we released the first version of the new architecture docs, the most upvoted comment was, I don't want to use Flow. Which I can totally understand. Like our first version of the docs were like essentially our internal wiki, polished and open sourced. And internally at Meta we use Flow, but outside that's not the case. So we had to rebuild a lot of like Cogent support. So now typescript is actually fully supported by Cogent. And I'll tell you more actually in 71, react Native 71, which is supposed to be released in the near future, matters of weeks at this point, typescript will actually be the default language. So the new projects will all be created with typescript. We are shipping types together with react Native. And we sort of took a closer look at our ecosystem and we thought like, we want to support typescript more. Next one on Android, Kotlin. So it's currently fully supported. Actually you can use Kotlin all over the places in react Native. I think the talk before will actually tell you a little, a lot more about it. So make sure you stay tuned. Our website is also fully migrated and bilingual. So all the examples on reactnative.dev are both in Java and Kotlin and you can fully use the one you want. And the template, as we did for typescript, we might also update the template to use Kotlin. We haven't done this yet, but this is set to open sometime in the future. And last one, Zwift. Well, a lot of IaaS engineer asking us to use Zwift and yeah, this is a little bit more complicated because of how Zwift and C++ interoperate. I hope to have answers for this in the future. We are keeping a close a look at it and yeah, hopefully we'll know more. So timeline. So what is happening and when? I mentioned some things, like some versions of react Native, but let me recap them. So we started early this year. Like the rollout of the new architecture started actually this year with react Native 68. That's the first version of react Native which supports those new APIs. Then in react Native 69, we actually added react 18 support. This is a little bit confusing, but effectively the way our react and react Native interact is that react Native decides which version of react to use. And the first version of react Native that supports 18 is 69. So you need to be in 69 at least. You can't just change it. And we ship bundled ERMs, which I talked about before. On 70, a lot of stuff and a lot of improvements actually on the experience related to the new architecture. I don't have time to deep dive on all of them, but some of those points have actually been highly requested by the community. So we released new architecture on 68 and people came to us and told us this is awesome, but it doesn't work for me because A, B, C, and D. And we heard what people were telling us and we developed a lot of improvements on build time, a lot of developer experience improvements and so on that made it into 70. And into 71, we simplified the template a lot. As I said before, we removed all the C++ code. Essentially now there is no C++ code at all unless you really want to see it because you might have, I don't know, your crypto library and you want to do your crazy stuff with C++. Then you can opt in and have C++ code that you are responsible of maintaining. And then what's next? Well, to the infinity and beyond, because as I said, we want to hear what works and what doesn't work for you. Like we want to hear from the community like, hey, yeah, this is valuable for me or this is not valuable. So please try those new APIs. They're still considered experimental. We are not enabling them by default. We will be doing that at some point. But in this stage, we are still collecting feedback and hearing from library authors, app authors, what is not working for them. I briefly talked about react 18 and react Native. Let me reiterate, just to clarify the interactions between the two frameworks. If you are on react Native 67 or 68, you are effectively running react 17, like the version of react is 17. And some of those new APIs, like start transition will not work. To use to fully use react 18 and all those concurrent APIs, you need to be at least on react Native 69. And you can't, you just can't change the react version like react Native decides for you. And here the catch is that on 69 and 70, to use those new APIs, you need to be on the new architecture, like you need to enable the new architecture to use concurrent react. If you try to use those APIs, but you're not on the new architecture, they will just not work. They will be empty implementations and so on. So it's crucial that if you have a react Native app and you want to stay up to date with how the ecosystem is evolving and how our framework is evolving, you take a look at those, yeah, at those new APIs. And what does it mean, take a look at those APIs? We created a lot of docs and we are still iterating on it. And it's actually all about the docs because those APIs, which we released in 68, were actually available there for so long. Like I think we added the fabric in react Native 64 or 65, but they were just not documented. I remember listening to this podcast, the react Native show, where folks were talking about like, yeah, some library are trying to use it, but don't know how they need to reverse engineer the framework code, which is not great. So that's why now we have an official doc. So you will find a new section on the website called the new architecture where everything is explained, why we did certain changes, how to create a new library, how to create a new app, and so on. And also a dedicated section on migration, like how do I go from a library or an app, which is non-architecture compatible to have default support for architecture. On top of this, we now have a new section called architecture, which contains design docs on how our internals work and how the render works and so on. Like people, especially like if, for example, Reanimated, which is a popular library, wanted to know how we work internally and what are the principles to follow and so on. So we took a stance and also wrote those docs. The new app template, like whatever happens when you do npx react native in it, my awesome app has been updated to let you try the new architecture easily. So what does this mean? It means that on iOS, instead of calling pod install after you set up your project, you will call RCT, New Arc Enabled 1, pod install. And this will reconfigure your project to let you try the new architecture. On Android, instead, there is a file called Gradle.properties and there, New Arc Enabled from false to true. And you can just react Native run Android and you will be running those new APIs. Effectively, you will see on Metro a message that tells you like, hey, you're running your app with fabric set to true and so on. So you are effectively running the new architecture. Real quick on a couple of other things that we also did, because I see I'm out of time. But a couple of content more. First, we started a working group. It's called the New architecture Working Group. And this is similar to the react 18 Working Group we started a couple of years ago. And it's a collaboration space where you can ask questions, share your libraries, give updates on how your library is migrating to the new architecture and connect with other people which are also looking into those APIs. If you open the working group, it looks like read only, but actually you can apply on the working group using the link below. And we're going to review your application and send you an invite. We also have samples, like stuff that effectively runs. So we have an app sample repo, which contains multiple branches. And every branch explains to you how to migrate to one app from a given version of react Native and so on. And every migration is done step by step. So you would see all the commits on how we enable the various stuff. We also have a library sample, which contains examples on how to create a turbo module or a native turbo module or fabric component, which is backward compatible. So you can create something that works both in the old and in your architecture. And with this, I really hope that in the future, when I search react Native new architecture, at some point, I will hear your stories. Like you will write about it and tell me like, hey, it was a complete mess because your folks missed here, here and there, or docs were great, or whatever. We really want to hear your migration story. Like we are iterating on this. We know some APIs are not as great and shiny as you like. And so we did update some of them. So that's why the old architecture is still experimental. And it's crucial now that people try this and tell us like what works and what doesn't work. Yeah, and I want to recall that all of our tools are actually open source. We are fully committed to this ecosystem. We spend a lot of time talking with partners, with library maintainers, and we just want to make those tools as great as possible and as valuable for everyone. Thank you very much for listening. Thank you very much, Nicola. It was like you enlightened us with the about the new architecture. And yeah, we do have some time for questions. Yeah, it's Yeah, we have some questions. And I'll start straight away. When is a good time to switch for existing apps to the new architecture? Or what's in your opinion, the timeline for switching to the new architecture? Or what dependencies? Yeah. So this is this is quite a crucial question. I would say. So when we started beginning of this year, we had a lot of libraries, like a lot of popular libraries, which had no support for fabric or turbo modules, which made immigration really hard, especially on fabric. Turbo modules are really backward compatible in a sense that you can just enable them. And if you have libraries, which are migrated libraries, which are not migrated, they will work well each other. On the UI side, instead, it's it's way harder. And we are actually taking a lot of effort on this side to let migrated and non migrated libraries work well together. Hopefully, there will be more on this topic in the future. But as of now, like my recommendation is to go through your list of dependencies and see most of them like a lot of them are actually migrated, for example, reanimated react native screens, they're all migrated and they have a version which is fabric compatible. But you might sometimes use a library which is unmaintained. And, well, that's unfortunate. I would say it's probably also an opportunity to take a stance at which libraries you're depending on and depending on libraries which are not maintained, it's generally like a security risk. So maybe it's also the opportunity for apps to take a look at what they're depending on and cleaning up some of those or potentially reviving some of those libraries, forking them and updating them. So I totally agree with you. It's like I saw so many great libraries migrating to the new architecture, like reanimated, react native svg, gesture handlers, and you also named screens. Yeah, it's there is a lot of traction also from the community. But I think that as a junior developer or someone that has no understanding of C++ or Kotlin or the new architecture itself is like really hard to just go and update something. It is. And that's also why we keep on considering the new architecture as experimental. Like again, is I would say, well, if you were to ask me, is it production ready? I will tell you, well, the biggest react native app, it's running on it. So well, it is production ready. It is. Is it easy to use? We are iterating on it. Like there are some rough edges, for example, on 70 build time on Android was like, people told me I need to wait half an hour to build on 71. We used to build time so much, like literally, like now it's a matter of seconds. And, you know, those changes requires feedback loop from your end and us also having time to fix them. All right. And I think we have a question which got answered during your talk. Do you need to migrate all the libraries to the new architecture? It is backwards compatible. And I think that you mentioned about backwards compatibility, but if you can add more. Yeah, let me reiterate. So the backward compatibility story is, as I said, a little bit more complicated on the two components, on the two pillars. Native modules. So whatever is not UI is backward compatible. You can use like once you turn on the new architecture, you can use turbo modules or legacy native modules, as we call them. On the UI instead, if you enable fabric, like if you enable the new architecture and you have a component which is not compatible with fabric, you will see like a purple box that tells you like, hey, here I should have rendered something, but this is not fabric compatible, so I can't render it. This gives you immediate feedback if something is going on or not. But we are also working with folks at Microsoft on a tool called AlignDepth or Depth Check. You might have heard it's part of this collection of tools called RNX Kit, which is a set of tools that Microsoft is building and they are like we are collaborating and iterating on providing more information on which library are effectively compatible with new architecture and not on the react Native libraries directory. There is a label that tells you like, hey, this is compatible or not. But yeah, I mean, once this whole thing will be stable, trust me, there will be an easy way to know which libraries are compatible and which not. Yeah, that was a great answer. And I also saw Lorenzo tweeting yesterday, I think, about AlignDepth and RNX Kit. It's like getting stronger and stronger, I would say, and to support this new architecture. I think I have one more question, just quickly. In terms of performance, did it worth all the work you have done? So for us, yes. We were able to develop feature like pre-rendering or do stuff that the previous architecture was not possible, like would not allow us to do. Now people come and say like, yeah, enable the new architecture and expect like, you know, spikes of gains here and there. That's not the case. Like the new architecture is, as I said, is a foundational stone for tools that you have to build on top of it. Like if you were doing something which was the bridge, then doing that with the new architecture, doing that synchronously, going from javascript directly to C++ will give you performance gains. But that depends on your use case. It's not that there is no immediate performance gain out of it. And yeah, it really depends on your use case, on your libraries and what you're doing. And we will see more and more libraries that will use those new APIs. And you will have to migrate to benefit from those new libraries. Great. Yeah. Thank you very much. Thanks a lot, Nicola. It's a pleasure to have you here.
29 min
02 Dec, 2022

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic