[HN Gopher] Migrating our largest mobile app to React Native
___________________________________________________________________
Migrating our largest mobile app to React Native
Author : cpeterso
Score : 80 points
Date : 2023-01-04 17:00 UTC (1 days ago)
(HTM) web link (shopify.engineering)
(TXT) w3m dump (shopify.engineering)
| pen2l wrote:
| 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.
| helsontaveras18 wrote:
| Why is this being down voted? Upon re-watching the video, I did
| notice a visible stutter in scrolling the app on the left.
|
| (To be fair, I didn't notice it the first time I watched the
| video.)
| danielrhodes wrote:
| 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.
| ricardobeat wrote:
| 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.
| meisel wrote:
| How did Shopify choose between React Native and Flutter?
| latchkey wrote:
| People are afraid of Dart.
|
| For the record, I think Dart is fantastic and really nothing to
| fear at all.
| jitl wrote:
| Flutter isn't native, React Native is.
| JimDabell wrote:
| React Native isn't native. It uses native UI components, but
| the application code is still just interpreted JavaScript,
| not a native application.
|
| https://reactnative.dev/docs/javascript-environment
| jitl wrote:
| Yes, but you can write and integrate the platform APIs for
| UO components. You can't do that in flutter.
| kayson wrote:
| UO components?
| chadrickman wrote:
| Platform channels -
| https://docs.flutter.dev/development/platform-
| integration/pl...
| revskill wrote:
| They bet hard on React ecosystem (for example, they accquired
| Remix).
| hooksfordays wrote:
| Shopify acquired Tictail, a Swedish e-commerce company that had
| their flagship app written in React Native. They worked on
| porting Shopify's Shop app to React Native, with great success.
| Subsequently, a 12-16 week experiment took place during which a
| small team explored rewriting one of the larger apps in both
| Flutter, then React Native. React Native was settled on
| primarily due to pre-existing knowledge of React and React
| Native in the company.
| h4waii wrote:
| 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.
| ageektrapped wrote:
| 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.
| kayson wrote:
| What was the rationale?
| ageektrapped wrote:
| IIRC, something about opportunity cost or maintenance
| burden.
| secretsatan wrote:
| There is virtually no maintenance burden if set up
| correctly, not shouting, i had to demonstrate the fact
| nprateem wrote:
| I'm sure it's only a vocal minority that care
| secretsatan wrote:
| It's so ridiculously easy to support though, and i may be a
| minority, but none of our users ever complain about it
| being there
| secretsatan wrote:
| 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
| pier25 wrote:
| 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.
| brundolf wrote:
| 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
| danielrhodes wrote:
| 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.
| fleddr wrote:
| The real reason is the shitty CPU on typical low-end to
| mid-end Androids. They suck at running JS. And I mean
| REALLY suck, as in 5-10 times slower than an iPhone.
|
| 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.
| danielrhodes wrote:
| Right. As much as people want to complain about Apple
| forcing WebKit/View on everyone, what it has enabled them
| to do is build specific hardware level optimizations in
| for JS and page rendering, which means you can get really
| good desktop-level performance even with an otherwise
| limited CPU/battery. Given Chrome's horrendous issues on
| MacOS, they are going to drain the battery as fast as
| possible and then blame it on Apple. Chrome users will
| then blame Apple for bad battery life.
| pier25 wrote:
| RN is quite inefficient and perf issues will not be obvious
| if using high end devices. Which is why Meta is working on
| Hermes:
|
| https://engineering.fb.com/2019/07/12/android/hermes/
| actualwitch wrote:
| Hermes is already enabled by default in rn.
| danielrhodes wrote:
| If you can get away with it, it's not a bad option. But
| it's still early days. If you run into compatibility
| problems or bugs with libraries being used, you could be
| in trouble.
| [deleted]
| siquick wrote:
| That's from almost 3 years ago. RN had changed a lot since
| then (and Hermes is included by default now)
|
| https://reactnative.dev/architecture/bundled-hermes
| JimDabell wrote:
| 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_.
| pier25 wrote:
| Honestly, as much of a pita it is to maintain two native apps,
| is this really worse than the huge overhead that was migrating
| to RN?
| threeseed wrote:
| 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.
|
| [1] http://djinni.xlcpp.dev
| [deleted]
| Eric_WVGG wrote:
| That's what really puzzled me about 1Password's switch from
| native Mac to Electron.
|
| 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?
| booi wrote:
| This probably works if a lot of your core code is not UI or
| presentation (dropbox sync, snapchat video filters). My
| guess is the shopify app is almost all presentation and
| their backend handles most of the heavy lifting and writing
| that in C++ is... not ideal
| booi wrote:
| This probably works if a lot of your core code is not UI or
| presentation (dropbox sync, snapchat video filters). My
| guess is the shopify app is almost all presentation and
| their backend handles most of the heavy lifting and writing
| presentation in C++ is... not ideal
| threeseed wrote:
| You wouldn't write the presentation layer in C++.
|
| 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.
| secretsatan wrote:
| I'm in two minds
|
| 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
| mhuffman wrote:
| I have had similar experiences on several decent sized
| mobile projects.
|
| 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.
| tsss wrote:
| Irrespective of this blog post, that is probably a good take
| away.
| sabellito wrote:
| Why?
| trevor-e wrote:
| 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.
| JimDabell wrote:
| This is what I was referring to:
|
| > 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.
| hajile wrote:
| That depends on what parts got ported. I worked on a large
| app where just a couple payment screens too as long as most
| of the rest of the app because there were so many business
| rules to take care of.
|
| 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.
| trevor-e wrote:
| "root screens" have a specific meaning and significance on
| mobile so I can understand the confusion, I agree that the
| article was not clear.
| hbn wrote:
| They explained earlier in the article that root screens
| were larger, high-impact screens at the top level of the
| app. They even bolded "root screens" the first time it
| was used to highlight it as a key word.
|
| It seemed pretty clear to me.
| secretsatan wrote:
| I'm pretty sure they mean the root of navigation stacks.
| They have high impact as it's the first thing a user will
| see and should contain all the most important features
| LAC-Tech wrote:
| Question for mobile devs - how viable is to share code betweeen
| native android and IOS apps? IE, all the user interface is done
| natively, but you share business rules, and maybe even an
| abstract view layer with names of fields, actions etc.
|
| 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?
| K0nserv wrote:
| I think Rust is one of the most promising languages for such a
| shared layer. Can also be used on the web via WASM. This
| enables native UI with shared business logic.
|
| Kotlin Native is another option that still allows native UI on
| the iOS side.
| LAC-Tech wrote:
| Promising - so not there yet in this capacity?
| david_allison wrote:
| It's there in this capacity (sharing a common rust backend
| between Desktop/Android/iOS)
|
| https://github.com/ankidroid/Anki-Android-Backend => https:
| //github.com/ankidroid/anki/tree/9f2920a063e9177cce082...
| K0nserv wrote:
| No, I meant more as in haven't tried it myself. Plenty of
| folks have done similar things with C and C++, I'm not sure
| if anyone has done it with Rust yet.
|
| 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
| Vt71fcAqt7 wrote:
| Flutter[0] lets you share the whole UI and really only requires
| per-system changes for thing like file system management.
|
| [0]https://flutter.dev/
| LAC-Tech wrote:
| Right but say you wanted separate UIs written in the native
| language for that platform.
|
| 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.
| Vt71fcAqt7 wrote:
| As I didn't make it clear, my response was to "Or are there
| other alternatives?" rather than to your main question.
| danielrhodes wrote:
| You can use C++/C to do this but depending on what you're doing
| it probably won't save you much time. You could also use JS to
| share code since both platforms have JS interpreters you can
| run arbitrary code in - but the ergonomics of this would likely
| be sup-optimal. For most apps, the vast majority of the work in
| mobile is the front-end - so sharing code this way would just
| end up being a headache.
| LAC-Tech wrote:
| Is mobile dev a bit like frontend web dev, where people
| really struggle to separate UI from business logic?
|
| Frontend web dev essentially had no concept of architecture,
| it was all code behind IME.
| danielrhodes wrote:
| More or less, yes. Because you have more opportunity to
| maintain state locally on a mobile app (which isn't done as
| much in browsers), you will see more business logic. But
| it's largely very similar to web dev. Again though: depends
| on what you're building and how much you need a remote
| backend.
| occz wrote:
| If you want to do code sharing on mobile between android and
| iOS, Kotlin Native is probably the most viable technology on
| the market.
|
| 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.
| secretsatan wrote:
| Cpp libs can mostly be used and it's the strategy we use, the
| main worry is trying to avoid massive sizes with dependencies
| up the yazoo in some of them.
|
| 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
| smith7018 wrote:
| 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.
|
| Love it lmaoo
| ageektrapped wrote:
| 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.
| weego wrote:
| 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.
| hooksfordays wrote:
| 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.
| fleddr wrote:
| I remember reading an article here a few months ago about a big
| company undoing their React Native migration, as it was a total
| disaster.
|
| Forgot the company name, anybody know?
| siquick wrote:
| Airbnb probably
|
| https://medium.com/airbnb-engineering/sunsetting-react-nativ...
| fleddr wrote:
| That's it, thanks!
|
| 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.
| Grim-444 wrote:
| 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.
| secretsatan wrote:
| 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
| 59nadir wrote:
| > [...] 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.
| secretsatan wrote:
| I can't really see an app like Shopify really needing
| specific native code
| brundolf wrote:
| 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
| hrpnk wrote:
| 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.
| koch wrote:
| > Making Improvements As We Go
|
| > 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?).
| mrbombastic wrote:
| 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.
| corytheboyd wrote:
| 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.
| hrpnk wrote:
| 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.
| null_object wrote:
| Where I'm working we're porting the native apps gradually to
| SwiftUI on iOS and on Android using Kotlin Compose - addressing a
| lot of the development speed issues mentioned in the article, and
| shifting to a 'reactive' model while retaining truly native
| performance and components.
|
| 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...
| zyang wrote:
| I think you made the right call here. SwiftUI had a slow start
| but now closing the gap on UIKit. ReactNative is a dead end.
| nodemaker wrote:
| As a former iOS UIKit dev I actually prefer react native to
| SwiftUI. If we have to do this declaratively (and I have to
| re-learn how to do complex layouts) lets also make it
| platform independent and reusable with Web.
|
| It feels like SwiftUI is being pushed down my throat and I
| have a strong aversion towards things like that.
| Jonovono wrote:
| As a RN developer for over half a decade - I just came to the
| same conclusion after doing a 1 hour SwiftUI course. Won't be
| touching RN ever again.
| [deleted]
___________________________________________________________________
(page generated 2023-01-05 23:01 UTC)