Migrating our largest mobile app to React Native
shopify.engineering
shopify.engineering
They seem really happy with their “We all get shit done, ship fast, and learn” progress, but I’m sure I’m not the only one reading this article and coming away less likely to choose to migrate to React Native, right? This does not sound compelling at all.
> Where We Are Now
> Here’s a spoiler: Today, if you open the Shopify Mobile app, all four root screens are in React Native already!
If you write “where we are now: we’ve ported all four root screens”, that’s what I’m going to hear. I’m not going to look through screenshots for contradictory figures. If they have actually ported 139 screens, maybe they should have said “where we are now: we’ve ported 139 screens”? As far as I can see they don’t say anything like that at all, are you inferring from screenshots alone?
Regardless, my point still stands – if you need to set up a training programme and a facilitation team and it’s going to be a multi-year effort, and after all that you proudly tell people that they can’t tell the difference between the old version and the new version… this still does not sound compelling at all, even if you have got almost a quarter of the way through the project in three years.
It seemed pretty clear to me.
If they prioritize the most important and complex parts of the system, they may be a lot closer to finished than the numbers would seem to indicate.
I got so frustrated with a cross platform technology i just wrote a native app to get away from it which the company later adopted. It implemented all latest native features, was tiny in size, and code base was easy to understand.
As it grows and our teams grow it does get harder, but also, if you’re using bleeding edge features, cross platform solutions can only cater to the lowest common denominator
The idea of a single code-base to rule them all is very seductive.
The reality, when you get to UI and hardware issues, is when you begin to get frustrated.
If your app doesn't need perfect hardware coverage, great hardware sub-system coverage (cameras in particular), and you have some cohesive UI design that won't irk people on seperate platforms ... then go ahead, React Native, or ionic, or flutter, or plenty of frameworks will work for you.
Otherwise, I think it is better to just bite the bullet and run two separate code-bases with pretty tight project managment to keep them synced.
For an app like Shopify where users often want to see revenue, sales etc in different environments using React Native seems a bit short-sighted to me.
I would've just use Djinni [1], kept most of the core code in C++ and then build native apps. Approach that Dropbox, Snapchat etc. took and seems to work.
It would be for all of your domain models, business logic and backend integration code.
You could even have Djinni generate the server side models as well.
The reason was, "we want code sharing with Windows". Okay, you've got that now… it's terrible… but you're also maintaining a SwiftUI app for iOS and iPadOS. Why not code share that with Mac?
I'd like to see some actual data about what percentage of their code is written in native vs RN. In my experience you need to maintain massive amounts of native framework code on both sides to support the RN code, and to implement stuff that RN can't do or does horribly. Adding RN into the mix just basically adds one more platform to be supported, making things more complicated, rather than combining code into fewer platforms. RN teams never bother to mention how much native code is needed to support them, and seemingly never include native work that was done when giving metrics about how long it took to "write" a feature in RN, usually because a separate "native" team does that work, not them, so it's conveniently not mentioned.
Also curious about other metrics such as how many developers they lost that weren't interested in becoming JS developers. Or have they stuck around because there's still so much native work that they need native developers for, to support RN.
Of course this is a mostly standard (but not small) CRUD app. We've got some custom animations/widgets here and there, but mostly it's vanilla forms, controls, views, etc. which translate easily to both platforms
We also started out on RN from the beginning; it's possible that migrating to it from native code is a much bigger challenge
In this case it seems like they transitioned a mostly native mobile workforce into React Native, so I don't know that the last bit makes much sense here. I agree with you that there is a general absence of information about how they still deal with the native side of everything with React Native becoming more and more important in their apps. Even just the "yet-to-be-transitioned-but-we-need-to-use-it" kind of stuff would've been more interesting to learn about and certainly "What native stuff remained in sections that were ported?" seems reasonable as well.
At the time of Blackberry 10, this was an appealing solution with Cascade. But now?
Even the mobile app we do have in qt has substantial coding in native. It doesn’t have things like faceid for login, light/dark themes, is extremely restrictive in supported devices and orientations.
There’s next to no community, anyone who does mobile just doesn’t use it, and imho, for very good reason, mobile dev moved on and supporters of qt just seem to like making it harder for themselves to support it.
I’d say it works ok on desktop, but i generally find qt apps on my mac look dated and have odd unmac like qualities.
Android has like 90%? worldwide market share and most phones are way underpowered vs even old iPhones. Picking a solution that only works well for SV users is a terrible decision.
I recently came across a ridiculous example of a high-end Chinese phone (700$) where one our web app's interactions that normally is near-instant, took 6s instead. Turns out that besides the generic issue of poor JS performance on Android (due to CPU), this particular manufacturer decided to deliver on their ridiculous battery life claims by...running all JS on a low energy CPU core.
Well yeah would you expect it to be otherwise? These devices cost a fraction of an iPhone.
People in the US don't realize iPhones are luxury products for the majority of people in the world.
"by...running all JS on a low energy CPU core"
Android including Chinese Android at best are ~75% market share.
But your point still stands though.
But yeah my point is that US devs (specially SV devs) tend to be myopic about this as they are using iPhones like most people in their bubble. If you're making an app for the US market then this is probably less of an issue, but for worldwide audience this is a huge issue. Not only with RN but with web apps too.
(To be fair, I didn't notice it the first time I watched the video.)
The reason for this is: React Native is on a run loop. And on each loop, new state is shared over a bus from the JS side to the native side. So if you manage the frames of an animation over this bus, it's going to be very slow. If the native side manages the animation, you don't have this overhead.
The same goes for touches. If you touch something, the native side gets the event and then this goes over the bus and RN picks it up. But if RN then responds to that touch by highlighting a view, that means another message has to go back to native - lots of overhead. For that to happen without a perceptible delay you have to have these events handled on the native side.
Another thing that can happen is too many things in the view change at once: you then have a traffic jam on the bus and the UI slows down or becomes unresponsive. This can happen if state changes too quickly.
You can get decent performance out of React Native (especially on tables, which is otherwise a dark art in iOS), but you have to know where the bottlenecks pop up.
The new Fabric architecture is supposed to reduce the native-to-js bridge cost significantly and might make performance on par with native - yet to be seen.
I can't fathom how broken each of their platform's codebases must have been to require everyone to learn a whole new paradigm to start over from scratch. Further more, they are presumably causing the same code quality issues because "React Native was a completely new tech stack for [their engineers]." So the codebases were so broken that they had to rewrite them and they chose a system that most of them are learning as they go.
Love it lmaoo
Shopify’s other apps that migrated first were either much older, and therefore had much more tech debt, making the rewrite more enticing, or were much smaller in scope, making the rewrite much faster to get to feature parity. Once all the other apps had migrated or decided to migrate, it made a lot more sense to explore it in the flagship app discussed here.
Some disclaimers, I’m no longer at Shopify, and while I worked in the very early iterations of the port of the flagship app, I wasn’t necessarily a vocal proponent of migrating it to RN. I enjoy RN, but I enjoyed working on the native Shopify apps.
As someone who uses the mobile app basically every day, it is absolutely one of the things that bothers me, every single time I use it. That's not a good thing.
Got shut down at the highest level. Like, definitively. As in, please don't ask again.
I don't think you'll ever see it as long as Tobi is CEO.
There are a couple of rare cases here and there, eg custom drawing using Core Graphics, where using cgColor won't pick up the change, you have to grab the underlying colour again and force a redraw
They were all coming from a non native mindset though
> As we port screens to RN, we also look out for opportunities to improve the UX of the app.
I would be curious to hear more about how this went - in my experience trying to do two things at the same time can lead to trouble, tempting as it may be (was it the migration or the upgrade we did along the way that caused this new bug?).
If you change UX as part of the migration, you're often unable to tell whether the cause was technical or functional. It's just too easy to say that it must be the technical side, but you don't have tangible data unless you actually compare the functional changes built on top of the same technical foundation.
Another aspect are behavioral metrics that may change between two implementations making these difficult to compare.
In React Native if something is slow or you want to use a recently-released native platform feature you can write a native component. That’s possible with Flutter too, but if you mix Flutter & native views, there’s a bunch of performance issues due to texture copies and thread synchronization.
For the record, I think Dart is fantastic and really nothing to fear at all.
Would you have to write it all in C, as that's the lowest common denominator for stuff that can be used in both swift and kotlin? Or are there other alternatives?
Again - not a mobile dev - but my spidey senses tingle when I see "cross platform UI". Feels like it won't go well, that different platforms have different conventions, that the abstraction layer will leak like a sieve, etc.
I’ll speak from the swift side, it’s improving a lot, but we’re still in a bit of a transitional phase.
With a swift package, you can include cpp libraries but still need an obj-c bridging layer, but afaik swift is becoming better at interoperability, but we maintain a few versions behind swift bleeding edge.
Android are also able to add their own stuff to the repos to make it work. So we basically have a mobile repo that can work for ios and android, pulling in cpp binaries as submodules
Kotlin Native is another option that still allows native UI on the iOS side.
Certainly more difficult than Flutter or RN, but if truly native UI is a goal I think it, along with Kotlin Multiplatform, are the best options
https://github.com/ankidroid/Anki-Android-Backend => https://github.com/ankidroid/anki/tree/9f2920a063e9177cce082...
Frontend web dev essentially had no concept of architecture, it was all code behind IME.
No, though i’ll admit it can be easy to get sucked into, bit that’s true for any platform, there are plenty of strategies to avoid this, mvc with uikit and swiftui further improves.
Just setting up test targets can mitigate this kind of thinking
Doing some MVVM-style solution where you share the model and view-model layers is probably the type of architecture you would want to go with, having both view layers merely subscribing to an abstract description of the view state living in the view-model and sending up commands to manipulate the view state.
As for being viable - it's certainly doable, but the technology is still a bit rough around the edges, and it's not at all certain that it's going to be worth the effort.
It isn’t popular. It’s talked about way more than it is actually used. 5.3% of mobile applications use React Native. 4.4% of mobile applications released in 2022 use React Native.
Forgot the company name, anybody know?
Summary: It was a massive pain and none of the benefits materialized.
Great thing to look forward to for Shopify. Let's meet here again in a year or two for the exit blog post.
https://twitter.com/tobi/status/1222551057798090752
There are quite a few high profile migrations that end up being reversed, it’s not just Airbnb. Some of them you hear about, like Udacity:
https://engineering.udacity.com/react-native-a-retrospective...
Some of them you don’t. For instance, Walmart wrote a lot about their switch to React Native here:
https://medium.com/walmartglobaltech/a-new-beginning-for-rea...
…but I believe they completely reversed course and went 100% native after that.
Developing in SwiftUI is lightning-fast - there are a few bumps and bugs that have been extensively discussed, but it's really simple to still use UIKit components in the places that need them (which are becoming fewer all the time).
For me the tone of the article is very 'positive' but the amount of time and effort seem horrendous. And now they're stuck with React. Not sure how many times these articles need to be written and then... [0]
[0] https://www.twopicode.com/articles/this-is-why-we-stopped-us...
It feels like SwiftUI is being pushed down my throat and I have a strong aversion towards things like that.
Even mobile web and non-web mobile are quite different platforms, even at the UI layer. There are many different expectations, platform norms, and interaction differences that don’t work well in browsers or across platforms. I’d love to seen an example of it working well but I haven’t yet.
Building both SwiftUI and Jetpack Compose apps is definitely a ton of work, but I think the right choice at scale. Before “scale” is “achieved”, I’d advocate for doing one platform well (there’s often an obviously more important one) and packaging the web PWA for the other platform.
The article is very cringe and I’m pretty sure not all the Shopify mobile devs are all in with the RN migration.