Back to News for Developers

Messenger Desktop: Faster and Smaller by moving to React Native from Electron

May 17, 2023ByChristoph Purrer

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.

Challenges with Electron

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.

Evaluating Alternatives

As a result of these challenges, we explored various UI framework alternatives such as Qt or the combination of AppKit on macOS + UWP on Windows and decided to use React Native Desktop for the newer versions of Messenger Desktop. We made this decision for several reasons, of which one was minimal code modifications. Since the existing Electron application was already written in React, we could easily reuse about 80 percent of the JavaScript code without modifications. React and React Native APIs are also very similar, which facilitated a smooth migration of the remaining code. In this case, we leveraged code-mod scripts to automatically convert the remaining UI components from a Document Object Model (DOM) based React UI to the corresponding React Native UI counterparts.

Another reason we decided to use React Native for Messenger Desktop is that React Native’s JavaScript Interface (JSI) library and its TurboModule system allowed for seamless transition from our existing NodeJS N-API add-ons to a React Native integration. The JSI system and TurboModules were also helpful for providing native parts where needed for replacing existing JavaScript functions. As a result, this simplified code and improved performance in scenarios that would have added an unnecessary jump between JavaScript and native code otherwise.

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.

Choosing React Native

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.

These are great wins for the people using Messenger Desktop everyday, as well as for our engineering team. With React Native, we can build and modify the entire application. As a result, we can identify and fix bugs within the underlying framework, which has allowed us to respond to Native or JavaScript crashes in our products much faster and more efficiently. It also enabled our product engineers to add or adjust features within React Native itself, such as adding improved context menu support and integrating animated GIF and WebP formats.

Challenges with React Native

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.

Partnering with Microsoft

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.

What’s next

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.