Editor’s note: This article was updated July 2021 with information about Flutter 2’s web support and an up-to-date comparison for React Native and Flutter. You can learn more about Flutter 2.0 here.
As developers, we are always on the lookout for tools that would allow us to save time and effort. We want to be able to write code and run it everywhere. With React Native and Flutter, this dream is slowly turning into reality. Because now, not only can we run apps on both Android and iOS, we can run them on the web and even desktop as well.
In this article, we’re going to compare each platform. Then we’re going to zoom in on their web capabilities to see if they are good enough to be used in production. Lastly, we’ll look at the pros and cons of each platform. After reading this article, you’ll be able to decide which one to use on your next project.
For us to effectively judge React Native Web and Flutter for web, it’s important that we first compare the underlying platform. We have to consider not just the web capabilities, but also the overall platform experience.
We’ll use the following criteria as the point of comparison:
How quickly can a beginner go from zero knowledge of the platform to a fully functioning app?
In React Native, it’s a multi-step process:
There’s one extra step required to run it on the browser, but that’s negligible because it’s only a command to install the web dependencies.
The steps mentioned above are from the quick start guide. You’ll need to invest more time when setting up your machine if you go the CLI route, though that’s something a beginner rarely needs to do since most of the native APIs are already implemented in Expo.
On the other hand, Flutter’s development setup can be summarized with the following steps:
For the web setup, there are a few additional steps you need to go through.
It looks pretty straightforward, but it can be pretty daunting for a complete beginner with little to no experience of the command line and no understanding of how to install different tools.
The community is another big factor to consider when choosing a platform. This community is the culmination of libraries and plugins, tutorials, forum/Stack Overflow questions, and GitHub issues that are out there.
React Native has more than a two-year head start, but that doesn’t necessarily mean it’s more popular. Flutter has 125k stars on GitHub while React Native sits around 97k. It looks like they’re receiving similar use: both have around 100k questions on Stack Overflow.
In terms of actual usage, according to the Stack Overflow developer survey for 2021, about 15 percent of all respondents are using React Native while about 14 percent are using Flutter.
However, React Native is a more popular option for web developers coming to mobile development because it uses JavaScript and a subset of CSS for styling apps.
Web developers are a spoiled bunch. Almost all of the functionality we’re ever gonna need in building modern web applications already has a corresponding library that implements it. All we have to do is learn its API and we’re good to go.
Flutter has a pretty decent plugin system that implements most of the functionality that is commonly used in mobile apps (e.g., social login, Google Maps).
React Native wins this because we can use almost any npm module (except for those node modules with native dependencies).
Another important factor when it comes to deciding which tool to use is developer productivity. This can mean a lot of things, so we’re going to break it down into the following:
To build React Native apps, you need to know how to write JavaScript code. While in Flutter, you need to know Dart.
Most people coming to explore solutions for building cross-platform apps using a single codebase are web developers. We want to reuse our existing knowledge of the web ecosystem to build mobile and desktop apps. This means that React Native is a more viable option for us since we practically don’t have to learn anything else to build apps using React Native.
Being able to find the things you’re looking for in a relatively short time and immediately grasp the information is another determinant of developer productivity.
Flutter’s documentation is more organized and more detailed than React Native. But when it comes to beginners, it can be pretty overwhelming to be greeted by tons of links. I like the simplicity of React Native’s documentation.
That said, we don’t stay a beginner forever. Once we gain more experience and get used to where things can be found, then it becomes easier. This is where Flutter’s documentation outshines React Native. Furthermore, React Native relies on a lot of community-written libraries, so its documentation is very fragmented. Meanwhile, Flutter has everything in one place.
As a new developer coming into an existing project, how easy is it to make sense of the way the code is organized?
In React Native, you can pretty much have any structure you want. Usually, it’s dependent on the size of the project and the various tools and libraries that your team has adopted. For example, using Redux will force you into a specific kind of structure since you will have reducers, actions, etc.
The situation is the same in Flutter; you can organize your code any way you want. But since navigation and state management are already baked into the framework, code organization can get more opinionated as well.
Hot reload is one of those things that can get annoying if a platform doesn’t support it. Being able to modify your code and see the changes on the fly as you save is a big productivity booster (especially on a dual-monitor setup).
Both React Native and Flutter support this feature, though it’s faster in Flutter if you compare it with Expo. There’s just a tiny bit of difference when compared to the CLI route for React Native.
Another important thing to consider is the debugging experience. In React Native, error messages can be pretty hard to grasp. While in Flutter, due to Dart being a statically typed language, the error messages it shows tend to be more meaningful.
React Native components translate to native UI components, so it has the same look and feel as a native app.
On the other hand, Flutter paints the UI elements using a rendering engine. It’s responsible for creating all the basic functions of each of the widgets. This means that there’s a constant effort on Flutter’s development to match the native UI behavior whenever there’s an update to the respective platform.
React Native only provides a few basic components. Though there are various UI kits available, it still cannot beat the widget collection that’s built into Flutter. The only downside with Flutter is that it has more widgets available for Android compared to iOS.
Both React Native and Flutter support native APIs for commonly used features such as image picker and geolocation. If you need a native functionality that’s not available yet, you can always write custom platform-specific code or create your own native module.
App performance is difficult to judge because it purely depends on what type of app you’re going to build. If your app doesn’t require complex layouts, transitions, and passing data to and from the native side, then you can choose either of the platforms.
However, when it comes to pure code performance, Flutter is the clear winner because the code that you write is compiled directly into native code. Unlike React Native, Flutter doesn’t have the concept of a “JavaScript bridge” for passing data between the JavaScript side and the native side of things. React Native’s “bridge” itself may soon be replaced by JSI.
Both React Native and Flutter have web support, the former being more of a community-led effort, while the latter is led by the Flutter team.
Web support for React Native is more mature than in Flutter. Web support can be added to existing React Native projects and Flutter projects, though they’re not really comparable. React Native Web compiles to actual HTML elements while Flutter uses the Canvas.
We’ll dive more deeply into web support for each platform later on in this article.
Does the platform support automated testing and deployment (provisioning, continuous integration, and deployment)? This can be optional for smaller projects, but crucial for larger ones. It helps us prevent bugs in our apps and not get bogged down by the manual deployment process.
At the time of writing this article, React Native doesn’t have testing and deployment tools baked into it. Just like for everything else, it relies on the tools built by the community. For testing React Native, we have the React Native Testing Library, Jest, and Detox.
When it comes to provisioning and deployment, there’s fastlane, App Center, codemagic, Bitrise, and Expo’s EAS build.
On the other hand, Flutter has built-in testing support (unit, widget, and integration). For deployment, it can be used with fastlane, Bitrise, Cirrus CI, Appcircle, and codemagic as well.
Flutter web is an implementation of Flutter that allows you to compile the Dart code you use for building Flutter apps into HTML, CSS, and JavaScript code.
Flutter web works by using web renderers. Simply put, they’re used for rendering a Flutter app on the web. Flutter uses two renderers: the HTML renderer and the CanvasKit renderer. The former uses HTML, CSS, and the Canvas API to produce pages. The latter is basically Skia for the web using WebAssembly and WebGL.
The main advantage of the HTML renderer is its compact size, though its disadvantage is its performance.
On the other hand, CanvasKit offers great performance but it has a poor startup time. This is mainly due to the additional 2Mb download size compared to the HTML renderer.
Users have access to widgets available for mobile. But developers have to consider making their apps responsive. Therefore they have to use widgets and classes such as LayoutBuilder or MediaQuery so that their apps will look great for whichever platform the user is using.
When it comes to plugins, not all of them have web implementation (e.g., ARCore, Filesystem access). In pub.dev, you can filter the results to only show the plugins that are available for the web.
React Native for Web is an open-source project by Nicolas Gallagher. React Native for Web makes it possible for developers to use React Native components and APIs on the web. The clear advantage of this is that it allows for code-sharing between multiple platforms, so you only have to write mostly single code and be able to run it everywhere.
Perhaps one of the first questions that comes to mind when you hear about React Native for Web is why not just use React? The answer to that is code sharing. If you use React, you can’t really take advantage of the tools that React Native has to offer. And you’ll be coding the same functionality twice.
Do note that not all of the native components and APIs are available to the web. This is because not all of them have an equivalent web API. The main thing that React Native for Web does is to map out the web equivalent for each of the React Native components and API. So the <View>
component becomes a <div>
, the <Image>
component becomes <img>
, and so on.
The second question that might come to mind is what’s the difference between React Native for Web and Expo Web? How do I know which one to use? Well, just like how there’s the standard CLI route for React Native projects, there’s also the quick start route, which is Expo.
Expo Web is just a nice addition that you get when you’re already building your projects with Expo. So if you already have an existing project, the main deciding point is whether you’re building your project in the standard CLI way or Expo. However, if your project is new, it will solely depend on what your project is all about. If you think you’re going to need a lot of third-party libraries with native dependencies, then you’re better off sticking to the standard React Native CLI. Otherwise, there’s really no reason not to use Expo since it just makes things that much easier for you.
Developers who plan to use React Native for Web have to worry about the following problems:
accessibilityLabel
and accessibilityRole
AppRegistry
to hard-code the HTML document string to be used for rendering the appTo wrap up, let’s take a look at what makes each platform great and not so great. First up is Flutter. Note that we’re not going to go over the good and bad points that are similar between the two platforms. Instead, these points can either make you “yay” or “nay” when it comes to choosing the platform that’s best for you:
Let’s now go over the pros and cons for React Native:
Just like every argument as to what’s the best platform for your next project, there’s no right or wrong answer. It depends on various factors that mostly boil down to your project’s performance needs and the relevant experience of your team. Does your project need butter-smooth UI interactions and animations? Does your team have existing experience with JavaScript? Are you willing to explore and use third-party solutions not provided by the core platform itself?
When it comes to web capabilities, I’d say that React Native for Web is production-ready depending on your needs. It stays more true to the technologies that make the web work because it simply compiles down to good old HTML, CSS, and JavaScript.
On the other hand, Flutter web is also production-ready depending on your needs. The main issue with it is really the performance. They have solved it using CanvasKit, but the user will have to wait even more to download the necessary scripts.
Overall, it’s an exciting time to be a developer because we can now reach more platforms than ever. All of that without leaving the comfort of the tools we know and love.
LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
5 Replies to "React Native Web vs. Flutter web"
Thanks for the info!
“Error messages are more meaningful because Dart is strongly typed” is listed in the Cons section for Flutter but it sounds more like a pro!
A year later, would you say things have changed regaring the maturity of flutter web (actually, of both frameworks)?
Why is Flutter bad?
“Error messages are more meaningful because Dart is strongly typed.”
Please move this under “pros”! For someone, who uses this article as a quick glance could get misguided.
You’re right — thanks for pointing that out. That item should have been included under the “Why is Flutter good?” heading. Fixed now!