Retiring React Native for Rust - Viktor Charypar - React Native London - August 2023

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
right hello and thanks for having me thank you all of you organizers for putting this on this is such a great idea of like two communities coming together and doing a crossover I'm gonna be talking about retiring react native in favor of rust I thought go hard or go home but but really the title of the talk should probably have a question mark at the end because it's not a story of having done it it's a sort of a story of an experiment born out of a bit of frustration and it's a frustration that is about all of this right it's it's the available options if I want to build a cross-platform app it's 2023 these are sort of the options I've got and I don't I'm not going to go through the individual categories of things like just have a look and and browse but I want to point out that there's a bit of a trade-off if I want a native ux that behaves like the platform like the user is expecting I kind of have to suffer a little bit in the developer experience and testing experience and the effort that I put on or I can do it quickly and relatively cheaply and we're a decent developer experience but then the the ux is not going to be that native because it's just sort of built once and then there is a sort of a happy middle ground trade-off of react native which I'm highlighting just because half the audience is react native so that's what I'm kind of going to be comparing to so none of them are a clear winner and that trade-off is there and I'm thinking you're looking at that and thinking well that's just like your opinion and you're right right like if before I get any deeper into this I just want to say that this is My Views based on my experience and what I've seen your mileage may vary and if you're a fan of react native and it's working for you more power to you it's great there is no one answer right and so yeah keep doing around me if it works for you um if any of this resonates maybe I have some better ideas maybe not um so I'm Victor I'm the tech director at a consultancy called red batter we we are a consulting company we work with our clients we help them deliver um digital products apps and websites typically quite large and complicated ones so we work with these sort of big teams building big products and seeing what it looks like at a moderate scale I don't want to say at scale because that just sounds like Facebook but like reasonably moderate scale and so that's the perspective I'm taking when I'm talking about these things and and yes I'm a bit of a rust fan hence the fairy speaking out right let's talk about react native and what did did when it came out in 2015 and how that compares to the situation today so when it first came out it was that a massive win over what the native experience looked like right it was cross-platform it had a declarative user interface which I think we can all agree is a better way of doing it by now I hope I hope that's not controversial anymore um it had better programming language because Objective C is just archaic and Java is not fun and and it had a developer experience of live reloading um whereas compiling the native apps just took forever and I just find it really interesting that now in 2023 a lot of that has been eroded like the the native platform has caught have caught up we've got declarative user interface toolkits in Swift UI and compose we've got better programming languages arguably better than typescript but that's just me um and the the live preview experience on both of those platforms also works and all of those things have been designed to work together so to an extent other than the cross-platform part it is maybe better on the native end but you know who wants to build things twice so there is still just one way of getting decent native feeling experience without building it twice separately so then what's the problem I think it's this like from what I've seen or what we've seen at Red matter in the various clients we work with it is extremely hard to build a good react native app a good native feeling fluid responsive native looking app and so I kind of want to look at why it's so hard to do that and do that with quality and continuously making sure that bugs don't creep in that it doesn't slow down over time in terms of development velocity and how hard it is to actually maintain and change when there are these big teams working on it sometimes multiple teams so I kind of want to look at like a bit of I don't know Theory I guess where how how do we ensure quality in building these things and I think that two parts to that it's the language and tools that we're using and then where they stop we fill in the rest with automated testing and I think both of both of those things have a room for improvement in react native and I kind of want to think about why and what you do about it so starting with language and tools that's the simpler one these are all of the ways that the languages and tools we're using are helping us with quality I can think of there's probably more strict static typing I think also no longer controversial that is a good way of getting quality in linting and style checking one interesting one I think is dependency management a sort of software Supply Chain management and making sure that the versions all work together and all the dependencies are declared and all of that sort of stuff test Runners to run the tests and all that sort of stuff and there is an answer to all of that in react native right those things problem I see is that they're also opt-in and add-on so there is a limit to which they can actually be relied on because all of them have been sort of bolted on to JavaScript and bolted onto the native ecosystem so they necessarily have Escape hatches because they have to be gradually introduced and so so your type checking is only as good as the nearest any type and that's kind of true for a lot of them you just can't quite have the confidence that they are there to catch you unless you're on a small team a really good discipline that you can rely on you just trust everyone which is true up until about 20 Engineers 30 engineers and then someone will just make a mistake and do it and then everyone will do it so there's a there's a limit to what the tooling can guarantee and that's where I think rust can help and so I thought I would do a brief detail interest for the people in the room I'm not familiar with it rust is all about strictness and explicitly stating your intent and safety and ensuring that things work the way you said they would so starting with the language is a compiled language statically typed language it's got a really good type system for modeling data which will be important later and so the example I've put on is modeling like a holiday sort of idea um you've got the start and end date where you're going and then the transport mode that you're taking that I think is pretty familiar and what I really like about the rust type system is the enums where you can say the transport mode is one of these things I'm either walking and that simple or I'm taking a car and then I need to know what route I'm taking or I'm taking a train from a station with the departure time and a ticket or I'm taking a flight an airport is a different thing than a station so I've got a different type for that so the the what's called variant of the enums can carry data and those data that data can be strucked they can also it can also be enums like further enum types it just all nests so you can model even a really complicated domain in these nested types and it's all just data the other thing that Russ does is generic types and traits so that you have to repeat yourself a lot this incidentally is rust's way of error handling it's a result type which is either okay everything worked or an error if it's an okay it's carrying some data type T if it's an error it's carrying an error type which is not any type it's one that has a particular Behavior called error that's called a trait and so it lets you constrain what you're working on whilst staying generic I'm not going to get any deeper into that because I don't have the time but there are people in the room who can help you with that and lots of documentation in books the community is super helpful as one of the really nice thing about rust then moving on to running rust it's interesting for our purposes because it doesn't have any run time it doesn't have a garbage collector it doesn't have like green thread runtime like go it's got like a predictable memory management system with a thing called borrow checker that brings a lot of memory and threat safety you can do async await it's pretty like high level apis for all this sort of stuff but not having your own time makes it extremely portable like there are microcontrollers that run rust and it's actually a really nice experience running rust on a microcontroller if you want to get into embedded development rust is the way and then finally it's got a really good set of tools where previously in the typescript slide there was like 15 different tools on the slide and rust basically needs just one kind of it's called cargo it's its build and testing tool it's package manager it's tool installer and Runner the only other tool that a lot of people use is called rust analyzer which gives you like live feedback in your idea about types and lets you navigate and all that sort of stuff so one or two and everyone uses that so you can sort of rely on that which is really nice so that's the end of the language side I think it's really nice and you should give it a go it's it's good fun and it it reduces your anxiety about code working like I don't know about you but in typescript code bases I just keep feeling paranoid like it says it will do a thing but occasionally it doesn't it betrays you and you're like well what's the point of all of the type checking if I can't rely on it moving on to automated testing where the tools stop we need to supply some more logic to make sure that the thing we said would happen actually happens and here I think is where we have even more room for improvement and that's not specifically true for just react native it's true for other places in my experience testing reactors hard work we've like seen teams who run CI pipelines with end-to-end tests that take eight hours and more just to cover all of the behavior it's slow it's brittle it's expensive it like this is again my opinion but I think it sucks like testing react apps is just a pain and I want to know why like what is what is behind it why is no one cracked it and I think it's because we build them how to test in the first place and I've tried to like put the finger on what it actually is and I think it's this ui-centric architecture of reactor actually this like does that where the UI layout is the primary organizing principle of the whole code base and then the behavior of what happens over time is secondary so it's kind of like if you wanted to say it in a sentence it looks like this and when you poke it with your finger it does that and that leads to State Management being sort of sprinkled around everywhere and effects being directly executed from all over the place when I say effects I mean sort of anything that interacts with the outside world so all input output disk Network apis everything to do with time random numbers basically everything that in your tests you need to intercept look at look at whether it's doing the thing that you wanted to do and stop from happening to make it repeatable and all of that is you know if I come back to this slide all of that is sort of all over the place so it's really hard to catch all of the instances of those things happening and say this is what the state of the world looks like for my test so that I can express the expectations this is like I just put this in because I think it's really cool have you seen this thing who has seen this sort of thing that kind of picture oh no one one person people call this the bed of nails it's a sort of a testing harness for printed circuit boards so these these golden things down there contact probes that touch the individual contacts on the pcbs and send signals and and read the signals on the PCB to make sure that it's doing what it's supposed to do in every little place because if you did a an outside in test like we end up doing with react apps most of the time the result you'd get is the PC which doesn't turn on like something's broken it doesn't power on so I think that sort of how we give up and test things end to end from outside in is just a bit insane like no one does that with complicated things and no one relies on it to that extent as we do it gui's and react apps specifically so is there a better way to build things so that we can test it better is the question that I want to try and answer and I think the key to it is to start with the behavior instead of the look and feel so I try to say what is behavior if you like boil it down and try to find the simplest most generic explanation of what behavior is this is although I came up with user interaction causes an internal State update and some side effects or in type signatures you've got a function that has some state a kind of a model of your application state it takes an event and it produces another state and a list of side effects if I saw the cover of that half that looks a lot like Redux right or Elm so the effects are the sort of addition to this idea and they Express what you want to happen and they take an event generically just because that's the sort of continuation if the when the effects finishes I want that event to be next is kind of the idea there so looking at the effects I think the core thought there is that you're taking the intent of the effect and splitting it from the execution someone else will do that later on some sort of runtime or platform or something so as an example in HTTP the intent would be the URL that you're trying to send a request to and the request itself the execution would be the process of doing a DNS lookup TCP connection sending some bytes all that sort of stuff so the calling of fetch in JavaScript is the execution the request in the URL is the intent and if you do that split the benefit is you can skip that in test you can just look at the description of the intent that's good thing for testing and then it can be different on different platforms which is a good thing for portability so there's like a double win in there and just to finish it off for the UI layout this should sort of look familiar that's kind of the react model right it's a function of some some model that produces drawing instructions slight downside is drawing instructions are platform specific so this is maybe more helpful you go from model to some description so the agnostic description of what goes on screen and then from that to the drawing instructions and the second one can be platform specific so to take that together we end up with like a behavior centering architect architecture where the behavior is primary UI layout and information display is secondary in other words it does this and it looks like that um and the interface of those things is data oriented they're pure functions you can test those really easily I provide the model in the event Look what comes out is that the right thing good so for getting out of the madness I think we need better safer faster language with better tooling and rust seems like a good candidate especially for the portability and we need a better architecture for the portability and testability in that shape or at least I want it to be in that shape and so you kind of know what's coming right and we built one and these guys in front and me um it's called cracks um it's a sort of a we say headless app development because you kind of build the apps inside out it is really young it's only like six months old it's an experiment um we haven't really seen anyone use it in production but we are desperate for feedback so we want you to try it it kind of looks like this um just one view um you've got the the middle green part is a core that is just logic and it's it follows that pattern of those two type signatures um it's pure it's just functions um and you write that once and it's portable across various platforms and then you've got shells around it that you can put it in and those are platform specific and they're responsible for the UI and also for executing the side effects that the call has requested and so those red things there are sort of different types of side effects that you can handle um they are sort of ports and then each platform delivers an adapter it's an old idea as well it's called platforms and adapters or hexagonal architecture data back to at least 2005 we didn't invent that either we just borrowed um same as the arm architecture that's inside so none of this is new we just put it together in in Rust all right one more point is that the rust core has to be pure because one of the platforms we target is webassembly and and that sandbox doesn't let us do any side effects anyway so we have to maintain it pure it's like really really simple app um which is pretending to be a payment terminal so you put some numbers in this is the like pretending to be Apple's new type to pay capability we can read cards on screen so that sort of screen would come up that's a placeholder it's not real and then you would go and tap your card some processing would happen and you get a receipt screen you push on hello at fake.com send yourself a receipt and we're done and we're back to the original flow really simple right so here is the sort of ideas that we've kind of already seen starting with the events that can happen it's an enum in Rust and these are the actions the user can take they can set the amount for the payment they can start it they can abort it they can send it once it sent we get an event that the send was confirmed they can set the receipt email send the receipt then that gets confirmed and then they complete the payment so those are all of the sort of things that can happen we've got a model which at the moment has a payment which is optional there might not be a payment in process it's worth looking at the payment just for the sort of modeling so payment has an amount and it has a status where's that gone there payment status is either new or pending tab or sent or completed with a receipt look at the receipts receipt has an email and a status again that's down here it's either new or pending or sent and that's the whole sort of model of the state there's a view module as well that's what we're putting on screen it's got a screen which is an enum down here and we currently support one screen which is a payment with the payment that we've already seen and then finally for the effects there's two what we call capabilities the sort of adapters one is render which just tells the shell that there is new stuff to put on screen and then there is a delay which simulates all of that processing because I'm not actually talking to payment apis but I could in the same way I just didn't have the SDK or the entitlement from Apple or anything like that so it's just fake delays so let's look at one place where we use this this is the update function actually sorry let me show you on here so the update function gets the event and the current state of the model and the capabilities that it can talk to and then it looks at what the event is and based on what it is it does stuff it's like Redux so in here for instance when we say send the payment if there is a payment in the model there is payment in progress we say send it which advances its own State that's just mutating the model and then we start a delay of two and a half seconds when that's done we want confirm send to happen once confirmed send happens we update the state of the payment again and it's the rest of it is really similar the tests I think are really interest interesting because we have I have this basic happy pass payment Journey which starts by making an app in this like testing harness the only difference between running the app in this mode and the actual mode in real life is that we get access to the model so we can set it to whatever we need it to be for the test otherwise it behaves exactly the same and so we start by setting the amount to 10 pounds it's in Pence looking at what the view is and making sure that it is so assert equal um screen is payment screen with that particular payment if we send it there is a new sort of a session in there and we want to see back a delay that's a request that we can eventually fulfill so that's one and also we want to look at the view and make sure that it looks like it what it needs to look like and once that this is simulating that the time has passed we just resolve it so we act as a shell for the for the app right we're resolved we said time is up here is the request just resolve it that results in some events specifically the one that we requested in the app we send that and we move on so this happens instantly in the test we're not actually waiting someone else will do that for us in the shell and just to prove that to you this is the unit tests for that that took five milliseconds to run it's just unit test raise fast so that's the core and it's worth looking at what the Shell Code looks like just to like finish it off so get ready to look at some Swift so this is like the report root of the app there is some View and it takes a core adapter the core adapter is quite small it does some serialization serialization stuff that will eventually hide from you but the principle is relatively simple there's a view which is a v-model this type is exported out of rust and replicated in Swift so you don't have to write that yourself we've got tooling that just produces that for you and there is an update function and a process effect function which is the sort of driving and driven side of the shell right so I can send an event in and then stuff happens and I process the requests that come back the requests are requests for effects so I look at that and if it's a render I'm just going to take the new state of the v-model if it's a delay I'll service that in the way that Swift can do not particularly interesting if you're not a swift engineer and just to show you what the view looks like it's like reasonably simple as a swift UI probably somewhat unfamiliar but hopefully readable there's a view it has a navigation stack inside of it as a switch looks at the view screen if it's a payment screen it will put this input screen on with some navigation title and some other stuff input screen is this one with like a vertical stack some spaces buttons with one two three so it's just describing what goes on screen using the data that came from the course so amounts text this amount and once I press one of those buttons it does this insert number which just calls update and it goes back to the call sends a message into the rust side of the thing that service is the state as we tested so this is I guess the point I'm trying to show is that this is really dumb it's just projecting the state out and sending events back in so there's not that much testing to do about this there's probably a little bit but not a whole lot we were after building a bit more complicated demo this is a note editing thing so I can say hello react native times rust I should probably zoom in shouldn't I the interesting thing about this is that underlying it is a oh sorry hey what am I doing is a crdt a conflict free replicated data type so it synchronizes other message passing so if I type into one it appears in the other and if I select something in this one go over there the selection sort of updates it just synchronizes across and it's it's messages and I just want to look at real quick what the tests of that look like because we can test the synchronization in in unit tests in the same way that we did in the other thing so this is an example of one of the synchronization tests what I can do in the unit test is create two instances of the app in the unit test because it's just a sort of data structure that runs some logic right so I make Alice and Bob insert Alice it runs an update inserts a world into its into her text document we take Alice's edits send them to Bob Bob makes an update inserts for hello um we take Bob's edits take send them to Alice Alice does some typing Bob does some typing and then in the end we look at Alice's View and Bob's view make sure they look like what we expected and they're equal and there is like 15 of those and then we'll run those two just to show you that nomadic is happening if I do that it will build I always does for some reason 36 milliseconds right it's just really instant because it's all unit tests and that's kind of I think the point that I was trying to get to is that you can do a lot of the end to end testing even quite complicated without having user interface without having network without having disk without having all of this infrastructure around it because what really matters is the logic of what you're doing what the execution of the thing so Crux is this this attempt of building this sort of architecture um for headless apps if you will um you build them sort of from inside out that note example is entirely test driven I started with the call build the call to the tests like feature by feature and only after I built the user interface um and it makes testing just a lot easier and you can run it pretty much anywhere I think even Vision Pro potentially we'll see when we get one and that's it that's me we really want your feedback if you're willing to try this and you like it give us a star that's the repo we've also written like a manual kind of book that you can read take pictures and that's it from me thank you [Applause] sorry but I didn't understand so I write an app in in Crux in Rust is every so when I build iOS up is everything converted to Swift or is like business logic in restaurant iOS yes the second um we compiled it as a static library and Link it into the IOS app and there is like a message passing bridge between it and the user interface so only the UI in Swift runs in Swift it's not transpiled it is running natively so I understand we need at least four languages rust Swift kotlin and let's say JavaScript I don't understand your point of saying this this makes testing easier because you said react native is difficult to test I don't know from which point of view you are saying but I see it as okay I'm a JavaScript developer I have to learn three other languages which I don't even have a clue how to test so I don't think it's going to make testing easier if you can explain about that maybe it's you're seeing it as a company that has three teams like if you can explain your point of view but from my point of view it does not make it easier because at least I have to learn three more languages and also I don't see the point of using rust at all because I will write JavaScript Swift and kotlin but why should I even use a completely Fair Point and a question I totally expected um yes this this does mean you're gonna have to learn a few more languages the thing about them is though they are extremely similar like typescript rust Swift kotlin they're all so close together now and also what's hard at least from my perspective about learning the shallow languages is knowing how to structure your app knowing how to like do the various architectures knowing the libraries knowing all of these things and you don't need almost any of that you just need the UI toolkit so in typescript it's going to be react you already know that and then Swift UI compose are not as hard to learn as all of kotlin and all of Android and all of iOS so yes I take your point you have to learn a few more languages but they are genuinely they are not that different like if I manage you will manage but yes it's a fair point you need to learn more languages and the I guess on the simpler point I mean more reliable predictable and way faster so you can run them on your machine you don't have to wait for CI for two hours so it gets you there faster so the time you spend learning the languages you read back in how quickly you can then move that's my perspective but obviously you can disagree yeah really fascinating stuff especially like bringing the album and Redux stuff into rust if you're dealing with a lot of App State especially in performance critical like UI stuff how do you deal with the fact that message passing is not always going to happen when you want it and inside the frame the frame budget so we haven't really looked at performance properly and I'd really like to see examples of what that's like for all of this sort of simpler stuff that we've been playing with it was never a problem it's really really quick already but I can see there's gonna be performance bottlenecks somewhere it's it's really young I don't have a good answer performance is going to be something we need to sort out at one point yeah actually I was building up on on the same question uh essentially you are trying to replicate the bridge which react native is getting rid of right in a way they use Json we use bin code it should be faster than that but yes there is a similarity there yeah performance is a bit of a question also I guess one of the points I didn't say but wanted to make is that you don't necessarily need to use rust or cracks to benefit from these architectures you can probably do that in typescript just as well um point I should have made and didn't and second is charge GPT able to generate a good dress code you'd be surprised it is actually like quite shockingly good at like when you write those tests that do that repetitive thing where you go move into the state and then this and that it just also completes the whole thing I have no idea how it does it it's just as as part of a JavaScript team I assume that you're trying you're rewriting your sort of core stuff you used to do in JavaScript in Rust and what was what's your experience with JavaScript because you know there's a there's 20 years of experience that there and and I guess you're doing it again from scratch well I think I would never argue to rewrite something from scratch as a like in bulk I would probably introduce it gradually like take a new piece of some really complicated functionality and start that you can mount the core into just like an edge of the app and leave it to do a thing my experience from going from JavaScript then typescript into rust is one of like relief is all I can describe it as like when rust programs compile I'm just like okay good this is done I don't worry which was weird right it's not strictly speaking true like obviously logical bugs can happen but the the feeling is hard to describe it's like okay cool rust's got my back this will work and it's like 99 of the time is true unless I said something completely dumb and it just does a different thing than I wanted and you're not trying to translate Legacy Legacy JavaScript into rust you're doing it if so I would do it gradually but no I'm not trying to yeah come come find me after if you've got more questions I'm happy to chat on that as well maybe before we finish for the reacts native react developers you mentioned a phenomenal Point like there's so many great fundamentals that I think have been embedded into the architecture that you guys have had by rust but it doesn't stop you from creating those boundaries yourself in your react native app today it's one of the things that we've been doing is defining very clear architectures so all of the stuff that we do I've seen it here and it's great that it comes pre-packaged into your into your framework so kudos to you guys on that yeah all of that is replicable in in typescript for sure thanks for that point thank you [Applause]
Info
Channel: Pusher
Views: 6,370
Rating: undefined out of 5
Keywords: developer language, language code, libraries, help, tips, forum, meet-up, meet up, learn code, coding education, coding hints and tips, lecture, coding lecture, learn about code, learn a developer language, amazon alexa skills, developer conference, node.js, javascript, backend
Id: CjbvmircpJ4
Channel Id: undefined
Length: 33min 59sec (2039 seconds)
Published: Thu Sep 28 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.