Chain React 2017: Breaking Down Bridging in React Native by Peggy Rayzis

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] you [Music] all right well thank you guys so much for waking up early with me today I know it's tough especially when you've been hitting the karaoke a little too hard or enjoying all the finest crafts I tour Portland has to offer so thank you so much for kicking off a two with me today now today we're going to talk about bridging and react native and this is a pretty heavy topic so I hope you all have had your coffee this morning I know I have so first I'd like to introduce myself my name is Peggy raiseth and I'm a software engineer at major league soccer on the UI team I write a lot of react native code both for our Greenfield react native app and also our real-time match experience on the web powered by universal components I also really love bridges both of the react native and the real-life variety and you'll see some cool bridges in my slides today so all right now that we got all the introduction out of the way let's start breaking down bridging now I'm going to use bridging as a verb a lot this morning and what I mean by that is how we communicate between JavaScript code and native code and react native so how many of you to show of hands would consider yourself a JavaScript developer okay okay a lot of you guys I consider myself a JavaScript developer too and I think anytime we start venturing into native code coming from a JavaScript background it kind of feels like this it feels really scary and the learning curve is really steep now this is actually a real bridge in Japan by the way and I'm from New York I don't really drive that much so the thought of this is super terrified but today we're going to make bridging feel more like this now don't get me wrong it's still pretty scary you're dealing with unfamiliar languages and concepts but once you learn a little bit about the mechanics and some tools to make it easier you'll start to see it from a new effective now luckily you won't have to reach for bridging too often that's why awesome tools like create react native app and Expo exist now for most simple applications you don't need to write native code even for most complex applications you won't have to write native code too often but it is useful to know how in case you have to now just to put it into perspective here's a language breakdown of our react native prototypes we built at the end of last year this is for a Greenfield application so if your brow field your statistics might look a lot different now for us the vast majority of our app 77% was written in JavaScript the other 23% were native UI components and modules about evenly distributed between Objective C Swift and Java now this is where bridging comes into play in order for your native code to talk to JavaScript you will need to write a bridge now although bridging shouldn't be the first solution that you reach for there are some situations where writing a bridge is necessary first you need to integrate a third-party SDK now at major league soccer we have a video platform that didn't have a react native SDK so we had to bridge the iOS and Android SDKs ourselves if you're doing any sort of video compression or image filtering where performance is really important you're probably going to want to move that from native and write a bridge module for it if you're building a brownfield application and reusing native UI components that you previously wrote you will probably be bridging quite a bit and also if you need access to platform AP is something maybe like the camera or the phone's gyroscope you will need to use an open source library or write a bridge yourself so I firmly believe that the key to understanding bridging is cracking in to react native in turn now too often we treat abstractions as a black box and don't try to see what's underneath the surface now show of hands who knows what the message queue is in react native okay not many of you and that's okay because I'm going to teach you guys about it and I'm also going to demystify some of the magic behind the react native bridge in hopes that it will help you learn bridging faster so here's a very basic cross-platform overview of the threading structure and react native so on the native side we have the main thread which is responsible for UI we also have the shadow cue which is responsible for layout calculations another important thing to note here is that each native module has its own thread or in the case of Android they share a thread pool now we also have a JavaScript thread and the way these two sides communicate is through the bridge so the JavaScript thread actually knows about all of your native modules at runtime they're injected into the JavaScript context of the VM as a global variable now don't worry if this sounds really confusing it's going to become a lot more clear later just try to remember that there is a JSON representation of each native module that looks like this to the bridge so now we're going to dive a little deeper into the mechanics of the bridge so when you interact with a need with a react native application all touch events start on the native side information about the touch event passes through the bridge where the JavaScript side reacts to the information in fact all communication passes through the bridge now this includes everything from creating views to network requests re-rendering a component and more and this is why it's really important to understand what's going on because it touches so many facets of your application so all communication across the bridge is asynchronous which is why you have to communicate via method calls and callbacks another thing to note about the bridge is that all messages must be serialized in order to pass across updates are also batch to improve performance now if you want to create some sort of mental map in your head this communication channel is pretty similar to a client and a server for example so all of these messages are handled by what's called the message queue which has a native part and a corresponding JavaScript part now the JavaScript part is really what we care about when it comes to performance if everything is getting passed through this message queue and the JavaScript side we need to make sure that the JavaScript thread isn't blocked and that the message queue isn't congested so if it is congested and the JavaScript thread is blocked we enter this really weird situation and maybe some of you have experienced this before we can scroll through the UI because that's all done media bleah but javascript doesn't register our touch event so if you're experiencing performance issues and react native I'd venture to say that it's probably related for the message queue so how do we get visibility into this and how do we prevent it from happening in the future so one of the best ways of preventing message queue congestion is limiting passes over the bridge this is actually what the react native team did recently with use native driver for animations first you send the configuration over to native the first time so that way you don't have to keep passing information across the bridge another thing you're going to want to do here is keep your data flat try to avoid nested objects and arrays because you're just going to have to use conversion methods to use the data and native you're also going to want to keep the data lightweight here don't try to send images encoded as base 64 strings over the message queue that's really going to slow your application down another thing you're going to want to do is write your business logic on one and that's going to help you limit passes across the bridge if you're unfamiliar with native languages my suggestion would be to keep your native modules spin and then write most of your business logic on the JavaScript side another thing you're going to want to do to gain visibility into what's going on with a bridge is to utilize logging and profiling tools and I'm going to teach you guys more about that today so let's dive into some tools that will make debugging the message queue easier so here's what a message looks like every single message sent over the bridge whether it's a network request or you know you're creating a view has this exact type signature so first you're going to have a type and that's a number that maps to whether you're communicating from native to JavaScript or JavaScript native you're also going to have the name of the module the name of the method and any arguments passed to that method the message queue also has a spy function that you can hook into to cause the laws the messages passing through so here's an example of what this looks like in our prototype at major league soccer so here a user is tapping on a video which renders a video view and plays it you can see here that the touch event actually starts with native now this five feature is pretty chatty and it's kind of hard to read and tell what's going on here we need a better way to isolate the specific messages that we're trying to debug in order to gain visibility with what's happening over the bridge so that tool that's going to help you accomplish that is called RN Snoopy I just want to give a shout-out to dote on Nate Holm who created it and did an amazing job with this tool it actually uses rxjs and treats the message queue data as a stream so you can filter out the noise and focus on what's really important so one of the cool things that you can do here is filter based on module or method so you don't get all that chattiness when you're trying to inspect what's going on with the message another really cool thing that you can do is trigger a yellow box warning and react native if messages cross a certain threshold so in this case we're showing a yellow warning box if we're passing too many arguments to create view which is something that could slow your application down ok so now that we know more about what's going on behind the scenes we're going to jump into how we bridge native modules and UI components so first you're going to choose your language now if you're building an open-source library I recommend sticking with Objective C and Java is their the most widely supported you can also choose Swift and Kotlin if you'd like I like these two languages because they most closely remember resemble flow type JavaScript so I feel a little bit more in my comfort zone when I'm working with them and actually I want to digress for a moment to talk about Kotlin because I think it deserves some attention on the big stage today so recently first-class language support was added for Kotlin was added to Android it's super easy to set up it's only about two lines that you have to add to your project and you can convert any Java file to Kotlin with a click of a button the runtime library is less than one megabyte so it won't add a significant amount to your bundle size unlike Swift which adds could be anywhere from three to seven megabytes also unlike Swift it works with react native link well not yet exactly the pull request was recently merged but this should be landing in a future version of react native very soon so anyone who has ever set up NAT native navigation by Airbnb knows how rough it is to not have react native link support so this is really huge that this is landed for Kotlin another really exciting thing about Kotlin is that first-class support for iOS is coming soon so while we won't be able to share native modules completely because of differences in threading across platforms we'll be able to read business logic which is really exciting and should be a huge time-saver so first I want to break down the difference between native modules and UI components because this was something that confused me when I first started doing bridging tutorials so the first thing you're going to want to choose is whether you want to build a native module or a UI component and most of the time you're choosing one or the other a native module does not render any UI it just exports methods and constants now occasionally you'll need to integrate both perhaps maybe you're building a video player view that also exports plane pods functions but this becomes really complicated because of how threading works in react native so first we're going to learn about bridging UI components now in a previous version of this talk I had a lot of native code samples but it felt a little aggressive for a 9:00 a.m. talk slot so I'm not sparing guys today and I'm going to teach you some high-level concepts that can be applied across platforms and show you a tool to make writing bridge modules a lot easier so whether you're building for iOS or Android you're going to have to construct a view manager now the view manager is what orchestrates the interaction between JavaScript and the view it's a factory that creates your view and only one instance of the view manager is created per Bridge so remember how I told you before that the bridge knows about all native modules at runtime well the view manager is like a special kind of native module except it returns UI and runs on the shadow queue the bridge has a reference to it and it has information about the component name and any constant if you're exporting them so on the JavaScript side if we want to construct the view we call require native component and that's what tells the view manager to create the view now it also checks the components interface via prop types to make sure that we are passing in any incorrect types to our component so now the vo manager it creates the view it also stores a reference to the view instance on the bridge so we can use it on the JavaScript side and finally in order to display the UI we render our native view and just use it normally as we would any other react component so alright that was a lot of information so let's recap what we just talked about here so here's what's most important to keep in mind when you're bridging a UI component only one instance of the view manager is created per bridge the view manager is a factory that creates a view and it's where you declare your constants and any props that your component will use this actually includes event handlers as well so any type of event handlers you're going to want to set those up in your view manager in this case the manager acts as a delegate for all of its view instances when handling events just like in reacts our view is where we cook up lifecycle events like layout sub views for example and if you want to render any children you're going to want to do that in your view so okay so we got UI components out of the way now let's talk about native modules they're actually a bit easier than ulai components because they just export methods and constants in fact a native component is a special type of module that returns UI so like we learned earlier all native modules are global variables at runtime they're represented by the JSON above and they include any methods and constants defined on the module so when we invoke a method on our module from napes from JavaScript we send a message to the queue with the method name and any arguments just like that type signature that we saw earlier when we were spying on the message queue logs the native side is what calls the method directly and if there is any information to pass back to JavaScript the method can do so either by a call back a promise or sending an event through an event emitter all right so let's quickly recap everything we just talked about only one instance of the module is created for bridge now this instance is initialized at runtime and if you want to communicate any data from needed to JavaScript you can do so with either callbacks promises or emitting events if you want to communicate data from javascript native you call methods on the native module and pass in any arguments which then transfers that message to the message queue now since javascript already knows about the modules constants at runtime accessing them at synchronous and you won't have to go through the normal bridging process so that was a lot of information here and I think no matter if you have a solid understanding of react native internals or if you're just getting into it bridging can be very prone to error and here are some reasons why so some of the pain points associated with fridging is you're constantly context switching between different languages and different files there's also a ton of boilerplate you have to remember to subclass from certain RCT view managers or in the case of Android you have to override certain methods and it's kind of confusing to get all this boilerplate straight the instructions are also really piecemeal you have you know some examples in the documentation but you don't really have you know a one-stop shop where you can get all of your information it's kind of scattered throughout various blog posts and tutorials there's definitely an opportunity to improve the documentation here so after experiencing all of these pain points firsthand I wanted to find a better way I also wanted to create a tool to make bridging seem a lot less daunting for JavaScript developers because it seems intimidating when you're first getting into react native and you suddenly have to write of code so I created react me to create bridge it's a CLI tool that generates bridge module and UI component templates in the language of your choice so the CLI is really easy to use you'll globally install it from NPM and run create bridge in the root of your projects from there the prompts will walk you through a series of questions you'll specify your module name what type of bridge you want to create and which languages you want to support and before you know it you'll have customised bridge templates that look like this another thing I want to point out is that I include links to the docs so you can read more in depth if you're interested now this was to make it as simple as possible for JavaScript developers to get started with bridging but I plan on adding a configuration option soon to remove the comments for more experienced users so react native create bridge isn't the only tool like this out there I would also like to recommend the awesome work of Johan Stein with react native create library there are a few key differences with our tools however Creek library is only intended to scaffold open source libraries it does not generate templates for UI components and while create bridge was originally intended to be used in existing react native projects it also works for scaffolding open source libraries I actually just recently talked with a shadow team they use it for their Shopify bridge and had a really great experience that they wrote a blog post about we also differ a bit in the languages we support so if you need to support Windows bridging in your project create libraries of really great choice and this is a feature that I plan on adding to react native create bridge soon if you want to get a little experimental and try Swift and Kotlin create bridge support step two and if there are any features that are important to you all when bridging please get in touch I'd love to hear from you all about how you're using Create bridge I want it to be a one-stop-shop for bridging so your feedback is really important to the success of the project so that was a lot of information but I want to leave you all with one more thing I think sometimes when we start venturing into unfamiliar territory and languages we need a little bit of confidence booster so don't be afraid to get your hands dirty and crack into the react native internals when dealing with native code I think now you're equipped with the tools and knowledge you need to make this happen so you got this thank you guys so much I had a really great time sharing my work with all of you if you have any questions please feel free to get in touch on Twitter or come find me later thanks [Applause]
Info
Channel: Infinite Red
Views: 6,768
Rating: undefined out of 5
Keywords: React Native, React Native Bridge
Id: GiUo88TGebs
Channel Id: undefined
Length: 23min 2sec (1382 seconds)
Published: Tue Jul 18 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.