They announced they were moving to React Native three years ago. Since then, they’ve set up a mobile enablement team, they’ve set up an internal training programme, and they’ve ported four out of three hundred screens [edit: see discussion below]. They are choosing to do it gradually because their estimate for a rewrite was three years. They are choosing not to go with the “new features in React Native” approach because their estimate for that was four to five years.
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 do you see they only ported four screens? In the dashboard screenshot it clearly shows "RN Screen Count: 139/572", so they've ported 139 screens, right? The "four" figure you're referring to is the root navigation screens of the app which get a lot more traffic, hence why they prioritized those to uncover issues.
> 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.
Also when you write an app for iOS you have most of the code to target watchOS, iPadOS, macOS, tvOS, realityOS etc.
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.
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
Well I give them props for at least having a facade of a "what went wrong" section, which most RN articles leave out, although it doesn't feel like an honest analysis of the negatives of their switch.
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.
Anecdotally we've got a RN app, and we've only got one or two native source files for each platform, which are mostly there to bridge in third-party libraries for things like analytics. Our UI and business logic are almost 100% JS and it works out really nicely for us
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
Same for us. Certain dev environments bugs were been a big pain in the ass for us in the past. For the logic side of thing React Native has been a nice experience for us as well!
> [...] 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.
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.
I’m one of few left in our company of our original mobile team after we switched to qt, and i pretty much soft quit by writing an entirely new native app
I would love to see their test using a regular Android device, not a high end iPhone.
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.
RN uses native controls (not a webview) and JS is plenty fast for most UI logic (it's almost never the bottleneck on slow web apps), so I would not expect performance to be a problem here
React Native is much slower on Android than on iOS, sometimes by orders of magnitude. You can get things usable on a lower-end Apple device, but on a lower-end Android an optimized RN app is still unusable. Part of this is due to the JS interpreter available on Android (which FB has tried to replace). But I think it's also due to architectural issues in Android itself and the natural overhead that RN has being too much in a constrained environment.
I like your confidence but obviously you haven’t released an app in an Asian market. Performance is an issue here since most are using outdated Android phones from average of 5 years ago.
You're right. Just checked it and in some markets like India it's about 90% but globally it's more like 70%.
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.
The scrolling/transitions animations are jittery in the left in the video, it’s a readily identifiable artifact of RN apps in fact, whereas the native one is incredibly smooth in all refresh transitions and scrolls. I wonder how difficult it is for RN to fix this. Just this one singular improvement in UX would be worth its weight in gold.
This is where things get interesting in React Native. The answer is: yes you can have smooth animations. However, the animations have to be driven at the native level and not in JS.
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 only stutter visible is during page navigation. Initially I even thought the right one would be RN. This is a solved problem in RN itself, with the default animation libraries already doing most of their work off the main JS thread. But it is extremely easy to overload React when all the extra rendering and business logic is put in, and it starts eating away the performance.
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.
So after three years, they've ported "all four root screens" in React Native?
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.
As someone who worked on the Shopify iOS and Android codebases, I would argue they weren’t all necessarily so broken. The flagship mobile app (the one primarily discussed in the article) was in good shape on iOS (and arguably better shape on Android). There was some fragmentation in architecture among teams, but overall things were reasonable and I didn’t personally find it difficult to jump into unfamiliar sections of the codebase..
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.
The choice to port to RN wasn't technical at all. Tobi (the CEO) prefers RN philosophically. No technical argument opposed to RN--which is super easy to come up with, along several axes--would have stopped the port. It was inevitable.
This is my opinion, as I watched it unfold. I'm no longer at Shopify.
It seems like the choice to use RN is usually made by the business side rather than engineers. I'm biased because I work as a mobile engineer but I've never heard an engineer emphatically love working with RN. In fact, I've usually heard horror stories about how it works, still having to write platform code, finding the talent that knows how to properly write RN, the fact that it's technically single threaded, etc. But hey, at least the higher ups get to hear "there's one codebase and therefore it's cheaper."
If he's willing to have the business fund it long term then fair enough honestly. But it seems like a weak strategy that isn't playing out well judging by the progress made over the 3 years so far.
Will another 10 years go by and there still won't be a dark mode for the app?
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.
Former Shopify iOS dev here. I pushed SO HARD to get dark mode to be a thing we would do. It's table stakes, IMO, in 2020 and beyond, to support it. We'd get roasted on Twitter, LinkedIn, just about everywhere. HN Comments, even. :)
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.
Ugh, i got a bit of pushback on supporting dark mode in my native app, luckily i was starting from scratch and once you show you can pretty much do it by setting up assets correctly and that you can switch modes from the quick menu to test, noone even thinks about it anymore.
They were all coming from a non native mindset though
The migration tracker is nice. Highly recommended approach for any migration project, incl. data migrations. It not only helps track the progress over time, but also provides great material for status updates. It's a perfect place to redirect stakeholders who have questions on the status or to help reduce their anxiety around progress.
> 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?).
Having done this, it goes poorly. You create new problems as you go because somehow, to the surprise of everyone, brand new ideas are less fleshed out than vetted ideas. Shocking.
Making technical and functional changes results in an inability to explain A/B tests that attempt to prove that the migration did not have negative effects.
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.
Agreed, you are almost always better off resisting that urge and taking note of things that should be improved as you go, otherwise scope balloons out of control.
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.
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.
[1] http://djinni.xlcpp.dev
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
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?
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.
https://engineering.fb.com/2019/07/12/android/hermes/
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.
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.
(To be fair, I didn't notice it the first time I watched the video.)
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.
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.