PWAs vs native web apps
PWA, React Native, or NativeScript. Which should you choose?
About 8 min reading time
Which approach should you take when building an app? Should you take up the PWA/web technologies route or should you go native and design for specific platforms? Both options have their pros and cons, and in this article we concentrate on a few of the popular choices used to create web and native apps.
PWAs (Progressive Web Apps) aka web apps, are built with popular web technologies HTML, CSS and JavaScript and work in a web browser. PWAs ) are effectively mobile websites designed to look like an app, and the use of web APIs gives them functionality similar to a native app.
PWAs vs. Native Web Apps: What's the difference? #
Progressive Web Apps have the advantage of being installable and live on a device without the need for an app store. And, part of the process is the Web App Manifest which allows developers to control how an app appears and how it's launched. Also, web designers/front end developers will already have the skillset needed to start building immediately. There's no need to learn a new language, unlike native apps.
Native apps are built with a specific OS in mind – ie. iOS and Android – and use a framework or language to fulfil that purpose. iOS applications typically use Xcode and Swift, and Android apps, Android Studio with Java or Kotlin. But, for this article we concentrate on a couple of JavaScript-based open source frameworks – React Native and NativeScript – that work for both platforms.
The advantages of native apps is that they typically bring better functionality as they make better use of a devices hardware and software, are faster and more responsive and you get quality assurance though ratings in app stores. But, it will mean having to learn how to use a specific framework or library.
Here we look at three different options – one for web (PWAs) and two for native (React Native, NativeScript) – for building an app. We run through how they operate, what they can do and look at their strengths and weaknesses to help you decide which option you should choose to build your app.
Native or Web? #
Don't worry, I'm not going to revive that old cold war, I just want to emphasize that today, that dichotomy of "Native or Web" is completely false. There are many definitions of "native" when we are talking about code and apps. For example, Progressive Web Apps can execute native code thanks to WebAssembly, and on Android, a native package container (WebAPK) is generated when the PWA is installed from the browser, and after that, it looks like any other app installed from the Play Store. However, PWAs are typically on the other side of the native world. That's because sometimes we define native as how we are distributing the app, definition that appears more than 10 years ago in that fight we knew as "Native vs. Web" but today with PWAs, concepts are not so hard. If it looks like a native app, it acts like a native app, it executes like a native app, maybe… Is it a native app? For some app developer purists, React Native and NativeScript are not native apps because a JavaScript virtual machine is involved.
Therefore, there are several possible native categories, and when you are discussing this with your clients, your project managers or your teams, it might be important to define the discussion first. We can be discussing the native code execution for performance reasons, the usage of native user interface libraries (such as UIKit, Android Widgets or AndroidX artifacts) or the usage of a classic native distribution channel such as the AppStore or enterprise distribution through an app package.
Progressive web apps: Building for the web #
Strengths of PWAs #
- Apps also work in the browser
- Distribution: browser, enterprise and app stores
- Can utilise React, Angular, Vue, vanilla or other frameworks
Weaknesses of PWAs #
- No access to every native API
- Abilities and store distribution on iOS and iPadOS are limited
- It’s in continuous evolution
PWAs are the current design pattern to create high-performant, offline, installable apps using just the web stack: HTML, CSS, JavaScript and browsers’ APIs. Thanks to the service worker and the web app manifest specs, we can now create a first-class app experience after installing for Android, iOS, iPadOS, Windows, macOS, Chrome OS and Linux.
To create PWAs, you can use any architecture: from server-side, vanilla JavaScript, React, Vue, Angular or other client-side frameworks. It can be a single-page application or a multi-page web application and we define how are we going to support users while offline.
In this approach, we don’t need to package and sign the resources of our app: we just host the files in a web server and the service worker will be responsible for caching the files in the client and serve them after installation. This also means if an app needs updating, you just change the files on the server and the service worker’s logic will be responsible for updating them on users’ devices without user or app store intervention.
In terms of distribution, the most common method is the browser. Users install the app from the browser by using the Add to Home Screen or Install menu item, by accepting an invitation to install or by using a custom web app user interface on compatible platforms. It is worth noting that Apple rejects pure PWAs published in the App Store and encourages web developers to distribute it through Safari.
The user interface is purely managed by the web runtime, which means the web designer is responsible for rendering each control on the screen. If you use a UI framework, such as Ionic, or a Material Design library, HTML and CSS will mimic native interfaces on Android or iOS but it’s not mandatory. When doing PWAs, applying web performance techniques is mandatory in order to keep a good user experience.
In terms of abilities, a PWA will have access only to APIs available in the browser engine on that platform and it can’t be extended with native code – with the exception of app store PWA distributions. In this matter, iOS and iPadOS are the more limited platforms for PWAs, while Chrome (for Android and desktop OSs) has more availability and is working hard to add every possible API to JavaScript with the Fugu project.
React Native #
Strengths of React Native #
- Same patterns as with React.js
- Some web APIs are exposed
- Web and desktop support
Weaknesses of React Native #
- Can’t reuse web UI components
- The native bridge needs some work
- React experience is needed
React Native is an open-source JavaScript-based component framework, sponsored by Facebook, that uses React design patterns, as well as JavaScript language to compile native apps for iOS, iPadOS and Android from one source code.
But no HTML elements are accepted for rendering; only other native components are valid. Therefore, instead of rendering a <div>
with a <p>
and a <input>
element with JSX, you will be rendering a <View>
with a <Text>
and a <TextInput>
. For styling components, you still use CSS and the layout is defined through Flexbox.
The user interface won’t be rendered in a browser’s DOM but using the native user interface libraries on Android and iOS. Therefore, a <Button>
in ReactNative will become an instance of UIButton on iOS and the android.widget.Button class on Android; there is no web runtime involved in React Native.
However, all the JavaScript code will be executed in a JavaScript virtual machine on-device, so there is no JavaScript to real native code conversion when compiling the app. There is a set of well-known APIs for web developers, such as the Fetch API, WebSockets and the browser’s timers: setInterval and requestAnimationFrame. Other abilities are deployed in the platform through custom APIs, such as animations.
You can start a quick React Native project with two free CLIs: Expo or the more advanced and official ReactNative CLI. If you use the official CLI, you also need Android Studio to compile and test the Android app and Xcode to do the same on iOS and iPadOS, so you will need a macOS computer for that platform.
React Native compiles native apps for iOS and Android, which means the distribution of your app will follow the same rules as other native apps: app stores for public apps, enterprise distribution and alpha/beta testing. Typically, you can’t distribute an app through a browser, although React Native for Web and Microsoft’s React Native for Windows platforms can help.
NativeScript #
Strengths of NativeScript #
- Good tools for coding and testing
- Extensive gallery of apps ready to play with
- All Android and iOS APIs are exposed in JS
Weaknesses of NativeScript #
- Small community
- Can’t reuse web UI components
- No web, desktop or React support
NativeScript is not as well-known as React Native but it competes in the same field: native iOS and Android apps from JavaScript and web frameworks. It lets you use JavaScript or TypeScript and an XML user interface file to create native apps. It also supports Angular and Vue right out of the box, so it’s a great solution for developers used to these frameworks.
The advantages of NativeScript are clearer when you use Angular or Vue. For Angular, you create the same components you are used to but using XML instead of HTML for the template, including all data bindings. In the XML, instead of a <div>
with a <p>
and an <img>
, you will place a <StackLayout>
with a <Label>
and an <Image>
component.
CSS and Sass are supported with similar styles to CSS in the browser. Routing and network management are done through implementations of the standard Angular services. For Vue, it’s something similar; you write the template in XML instead of using HTML in the same <template>
element in your .vue file.
NativeScript includes a collection of components that are then mapped to an Android or iOS native control, so when you render a list or a picker, it will be the native app, using the same idea as in React Native.
Your JavaScript or TypeScript code (transpiled) is executed in an on-device JavaScript virtual machine with a bridge to/from the native environment. In that bridge, the entire native APIs from Android or iOS/iPadOS are exposed so despite having access to cross-platform APIs, we can instantiate or call any Java or Objective-C code from JavaScript/TypeScript and NativeScript will marshal data types.
NativeScript has great support for tooling, including VS code plugins, the CLI, a hot-reload testing system and a NativeScript playground app, so you don’t need to install all dependencies while testing, as well as several additional services such as an online playground.
Finally, NativeScript only compiles an app for Android and iOS that can be installed from official distribution channels and app stores if you comply with their rules, enterprise distribution and alpha/beta testing. Typically there will be no way to distribute apps from a browser and there are no solutions for desktop apps for this platform.
Other solutions #
We've covered the three most important recent solutions to create cross-platform apps today using JavaScript and some of the well-known frameworks: React, Angular, and Vue. But there are other names worth to mention in this list, all of them open-sourced and suitable for native app development for store or enterprise distribution only.
Xamarin #
It's Microsoft's solution to multi-platform app development. Instead of JavaScript, we use C# and .NET and we develop and design screens using Visual Studio. Today, it can create apps for Android, iOS, Windows and macOS, sharing some code and some screens using the user interface kits of each OS.
Flutter #
It's the recent platform from Google to create apps for iOS, Android and also the Web (targeting the DOM and Canvas). Instead of JavaScript, we use Dart and we define the user interfaces in a JSON-like declaration within Dart. Dart doesn't use OS user controls, but it creates an almost pixel-perfect high-performant user interface for Android and iOS.
Apache Cordova #
Not new, but worth a mention here. The heart of the well-known PhoneGap, the tool let us create hybrid apps: web apps wrapped in a native container using a WebView. Here we can use a Vanilla JS solution or any web framework to render and design our app, with the ability to call native plugins for hardware and platform access.
Some examples #
When deciding which platform to use, reading about and testing other apps and their experience might be a good idea.
- Many big names published PWAs including Twitter, Starbucks, Google Maps and Uber. Uber found a new niche by supporting desktop with PWAs [https://eng.uber.com/web-booking-flow/]
- React Native is used not just by Facebook apps, but also Uber, Skype, Pinterest and Salesforce among others [https://facebook.github.io/react-native/showcase.html]
- Many banks have decided to use Native Script to leverage their Angular developer experience with success, including the European banks Raiffeisen Group and Triodos [https://www.nativescript.org/success-stories]
- Airbnb used React Native for two years and they've released a report on what worked and what didn't before deciding to move away from it [https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology-dafd0b43838]
- Sometimes developing native apps is not needed and many apps using that technique can be better apps as PWAs, @ShouldBePWA Twitter account collects some of them [https://twitter.com/shouldbepwa]
This article was originally published in issue 325 of .NET Magazine, but this version has more content.