React Native has been an excellent tool for creating mobile applications at Meta. It allows us to build feature-rich mobile experiences reaching millions of users every day. With growing demands for our desktop applications, our team explored whether React Native could provide similar wins for desktop development at Meta. We were able to partner with Microsoft to rewrite Messenger Desktop with React Native for Desktop. In this post, we'll go over the challenges we had with Electron and why React Native was the right choice for us.
We have used Electron for various products at Meta since early 2016. These desktop applications often started as web experiences wrapped in an Electron shell, which was later converted to a native application to enable a more feature-rich desktop experience. Overall, this represents Messenger Desktop’s product and development journey between 2018 and 2020.
In early 2021, we shipped our first React Native Desktop surface within the Messenger Desktop Electron shell, providing a modern and state-of-the-art calling experience based on our RSYS library. As this validated that React Native on Desktop was a viable choice, we then converted the rest of the application from Electron to React Native and shipped it less than a year later.
With Messenger Desktop’s growing popularity, in mid-2020 we re-evaluated using Electron for several reasons. First, Electron’s binary footprint is large and on the operating system (OS), we had to ship up to 200 MB just for the framework itself. We also received lots of internal and external feedback about slow startup times, especially on low-end Windows devices and higher than expected memory and CPU consumption when idling. Additionally, there were many crashes from the Electron native code which we could not easily fix since we didn't build Electron from its source, due to its complexity. Electron’s two process architecture also proved to be an issue since it required inter process communication between the UI and the main process, which added extra overhead when integrating our custom native modules, such as the MSYS messaging library or the RSYS calling library.
We encountered an additional issue while implementing AR effects like background blurring which required our own native webRTC stack because no webGL solution existed at that time. Our webRTC stack, which is shared with mobile apps, requires us to render video streams in our custom component. With Electron, we couldn’t efficiently render directly in an HTML canvas from C++. Although we could accomplish this by forking Electron (specifically, Chrome), we didn't apply this method since our product teams are focused on building business logic written in React.
Finally, React Native macOS and React Native Windows are fairly small and can be built from sources quickly. We found leveraging the Apple and Microsoft UI components in React Native could also provide the experience that felt more native to the OS. This was especially apparent on low-end Windows devices that we anticipated having significant startup performance gains.
Migrating Messenger Desktop from Electron to React Native reduced the final binary size by over 100 MB both on macOS and Windows. App loading time was reduced by 50 percent for the great majority of our users on macOS and Windows. Native application crashes have reduced by 15 percent on macOS and 67 percent on Windows. The metrics collected with either neutral or positive impact include: daily active people using the product, talk time and messages sent metrics.
Although React Native Desktop solved many engineering problems, it also created new ones. There is no single multi-window handling component for React Native Desktop out of the box. As a result, we created our own that's currently tailored for Messenger Desktop’s needs. There’s also no auto-updating support. To address this, we integrated the Sparkle updater and wrote scripts to create installable packages both on macOS and Windows. Additionally, we created other custom components to easily define and control application and system tray menus for both macOS and Windows. Finally, since there is no official end-to-end (E2E) testing solution available for React Native Desktop, we extended our in-house E2E infrastructure to support Desktop applications.
The React Native Desktop ecosystem is more limited than the mobile ones. Therefore, without a team experienced in both Apple’s AppKit and Microsoft’s WinUI platforms, it can be harder to create such components from scratch in a short period of time.
With Meta’s adoption of React Native Desktop, we are working together with Microsoft to continuously contribute improvements to the React Native macOS and Windows GitHub repositories. We are currently collaborating on New Architecture and C++ TurboModule support on macOS and Windows. We have made sure that react-native compiles with clang and MSVC compilers and have benefited greatly from Microsoft’s expertise in the WinUI framework.
Overall, the benefits we have seen with React Native outweigh the drawbacks we encountered. We are optimistic that with continued contributions to React Native Desktop, we can reduce start-up costs for other teams in the future. Once our custom React Native Desktop extensions are mature enough, we will revisit the topic of making them Open Source.
Due to the overall benefits, Meta wants to continue investing in React Native for our desktop products. In addition to Workplace Chat, our business-focused instant messaging client, we are working on various other React Native Desktop based applications, some of them started from scratch and others following a similar migration path as Messenger Desktop.
Thank you to everyone who contributed to React Native Desktop.