Skip to content
Logo Theodo

React Strict DOM: The Future of Universal Apps with React Native

Mo Khazali10 min read

A React Logo with several devices in the background

A couple of weeks, Meta announced the release of react-strict-dom. I can’t stress just how a big a deal this is. Fundamentally, this will change the way we use React Native (and React on web, for that matter). It provides a unified set of UI primitives with styling that can be used across the board on web and mobile! Now, being able to “write once, and deploy everywhere” isn’t news to anyone who’s been in the Universal RN space - react-native-web has been around for years and can handle the translation of RN’s primitive to web DOM elements. This was a RN-first, web-second approach and it came at a cost.

This article looks at why react-strict-dom matters, how it differs from react-native-web, and why you should be excited!

Background

Attempts of sharing RN UI on web & mobile

A timeline of significant milestones in using React Native on the Web

The vision of “write once, run anywhere” developed pretty early on, after the release of React Native in 2015. People started thinking about how they can use RN across both web and mobile. Nicolas Gallagher released React Native Web in 2016, as an interoperability layer between React Native and React DOM, essentially converting RN’s Components & APIs to web components. React Native Web was used by Twitter Lite to create components for the web only and is still powering the majority of its components for Twitter on the web today.

Separately, the folks at Microsoft developed ReactXP, which was their take on how to bridge the UI layer gap between React on web and React Native. This project gained a lot of traction and was used on Skype. Ultimately, ReactXP was deprecated in 2020.

In the meanwhile, React Native Web matured over the years and started covering more APIs that were important to the web. It added wider support for accessibility, SSR, among other minor improvements.

Meanwhile, the folks at Expo had also been working on the universal vision. Back in 2019, Expo announced support for web going into beta. Since then, Evan Bacon has been hacking away at building out Expo’s vision of RN on Web. In 2020, Evan released a demo of how Metro could be used to bundle web apps. Fast forward to 2022, Expo Router is announced, which is Expo’s take on how a single codebase could power web and mobile using a navigation router that follows both web and mobile standards. Expo Router uses Metro under-the-hood, which unifies the bundling process for the web and mobile versions of apps.

RFC to reduce API Fragmentation between React DOM and React Native: react-strict-dom

In August 2022, Nicolas Gallagher, the creator of React Native Web created an RFC proposing that there should be an effort to reduce the API differences between React on the web, and React Native. It was initially dubbed “strict DOM” which was a subset of React DOM.

The goals of this RFC was mainly:

This was being worked on for over a year by Nicolas and others at Meta (along with quite intensive discussions and suggestions from the open source community), until it was launched in February 2024.

Why does react-strict-dom matter so much?

While the vision of universal apps has been long in the making by the community, it was never “endorsed” by Meta until the release of RSD. Meta always pushed a “Learn once, write anywhere” mantra, implying that React Native can be used for multiple platforms, but requires different implementations for each platform. This is the contrary to the “Write once, run anywhere” vision that the community have been pushing towards. RSD is the first official endorsement by Meta of cross-platform UI across web and mobile.

Digging a bit deeper into the details, these are the main reasons why I think this is a really big deal!

Meta themselves dogfooding it

When you look at the react-strict-dom repository on Github, it mentions that Meta’s team are already using RSD in production to “ship features faster, to more platforms, with fewer engineers”.

Having the direct investment of Meta in a “universal” solution for UI means that it will accelerate its development. On top of that, if Meta is using it in their applications in production, it will mean that it’ll be battle-tested on some of the most intensely used websites/apps out there, which will naturally mean that it’ll be extremely optimised and scalable.

Improved performance on web

One of the problems I’ve had with React Native Web is that it is quite a chunky (no pun intended) dependency. If you don’t have tree-shaking enabled, the bundle size is close to 300KB. Adding this atop the ~125kb for React-DOM, you have around 425KB in dependencies just handling your bundling (granted these are the uncompressed sizes). This is because React Native Web tries to cover the entirety of the surface area for React Native APIs, and as such, will have to support loads of functionality that you may not want to use on the web.

For example, the Animated API is in react-native-web over 70KB in size, and relies on the JS layer to execute animations, which is slower than just doing it with CSS. Similarly, you may not want to use the VirtualizedList, PanResponders and other components that are part of the React Native ecosystem on web.

Diagram of the React Native Web source map with the Animated API highlighted

With react-native-web, the burden of translating and supporting APIs is on the web app, which arguably has less room for performance hits due to things like SEO rankings.

React Strict DOM takes an almost opposite approach. It puts the burden of compatibility and translation of APIs to the mobile side, where there is arguably more resources available to handle the burden of taking APIs and mapping them to native layer functionality - if anything this performance hit is already there at the core of how React Native works, where the JS layer has to delegate Views, Texts, and other elements to the native layer implementations.

Opening the React developer pool closer to React Native

One of the major deterrents for web developers switching from React to React Native is the major difference of APIs. Web developers are used to the DOM, and it’s one of the things that makes React attractive in the first place. You can use <div>s, <input>s, <button>s and pretty much any other elements that exist in the DOM with little to no modification (the biggest gotcha for people initially is usually switching from class to className).

React Native is significantly more limited - there is a defined set of APIs that a developer needs to familiarise themselves with that is similar to, but fundamentally quite different to the DOM. This means that there is a significantly larger learning curve for developers to start using React Native.

RSD embraces DOM elements and removes this cognitive load for developers moving from React by introducing APIs that are far more familiar to React developers.

It’s not just APIs, as part of the RFC, things like the React Native event loop are being redone to bring them closer to the web event loop.

Initial concerns

Performance on Native Devices

One potential concern with the shift of the translation layer from the web side to the native implementation in React Strict DOM is whether it might negatively impact performance on mobile apps. React Native has struggled with its reputation regarding performance, so it’s important that this is tested and there aren’t any regressions from using RSD.

To get a sense of the performance implications, I conducted some preliminary tests using Flashlight. I rendered 1000 items in a Flatlist (manually overriding any virtualisation) with each having a view and some text.

From my basic tests, I’m seeing nearly identical results between React Native and React Strict DOM, which is an encouraging sign. However, this is a very basic test, and the surface area needs to be much larger, testing more the API surface area to get a more accurate idea of performance implications.

A flashlight test showing performance being identical between RN views and RSD

Practical adoption plan for existing universal apps

Another consideration is how straightforward it will be for existing apps using react-native-web or just regular RN to migrate to react-strict-dom without requiring a massive overhaul of their codebase. Ideally, there would be a smooth migration path that minimizes the need for extensive manual changes.

A few ideas that came to mind was to leverage code transformations to handle a significant portion of the migration automatically. This might involve a custom Babel configurations or other build-time tools to convert existing React Native Web code to React Strict DOM compatible code.

Another approach could be to proactively abstract UI primitives into custom components that currently use React Native Web but can be easily swapped out with React Strict DOM equivalents in the future. By building this abstraction layer early on, the transition to React Strict DOM could be significantly easier.

More realistically though, popular universal UI libraries like Tamagui and Gluestack could also play a role in easing the migration by abstracting away the underlying differences between React Native Web and React Strict DOM. Since these libraries already have abstractions on top of the RN APIs, by virtue of them adopting RSD in the future, apps that are built on top of these libraries should be able to switch from React Native Web to RSD with minimal changes to their codebases.

When will it be stable?

Which leads naturally to the last point. RSD was announced a little over a month ago now. It is still in the experimental phase, and the timeline for when RSD will be production-ready is still unclear. There is still a large part of the surface area of APIs that needs to be covered before it can be prod-ready for native apps.

The original RFC was opened in summer 2022, which indicates that development has been going on for around two years now. Given the scope and complexity of the project, it wouldn’t be surprising if it takes another year or two before it’s fully stable.

Wrap-up

This is an incredibly exciting time for the React Native community and the wider React ecosystem as a whole. Seeing Meta step into the universal app space with RSD means that the vision of having a single codebase that powers native apps + web is being embraced by big tech. This effort will mean that as a community, we will see better quality, more performant universal apps, with loads more tooling to facilitate building them in the future.

It’s a future that I am very excited about!

Liked this article?