I was recently contracted out by a Fortune 500 company to research the feasibility of implementing either React Native or NativeScript as a future mobile solution for a specific software product within the company. I spent over two months building a prototype application in each framework and documented every highlight, pain point and milestone along the way.

This is not an expansive, all-encompassing review of every strength/weakness of one framework versus the other, but it does touch on some key findings. Although I do cover a lot, I’m sure there are many more topics worth covering and would love to hear from you if you have some in mind.

I was told to focus on these eight topics while conducting my research:

  • Testing and Debugging
  • Continuous Integration
  • Running an Application –Emulators and Device Management
  • Platform Tools
  • Access to Native APIs
  • Responsiveness
  • Compatibility
  • Completeness of Platform

I reviewed these topics for each framework and documented exactly how each process is achieved. After further ado, here are my findings!

Note: The company is an Angular shop, and some of my conclusions are based on that presupposition.

Testing & Debugging

Unit Testing
NativeScript

The NativeScript CLI allows you to test all JavaScript-related functionality within your application. You cannot test any styling and UI capabilities that are not applied or created via JavaScript. There are three testing frameworks recommended by NativeScript: Jasmine, Mocha or QUnit. Similar to a standalone Angular web application, the unit tests can be developed in Typescript/JavaScript and utilize Karma as the test runner.

React Native

React Native uses a Facebook-backed JavaScript testing framework called Jest to do all its Unit Testing. React also highly recommends implementing Flow, a JavaScript linter that checks your code as you type.

Debugging
NativeScript

NativeScript’s debugging capabilities are good, not great. There are a few existing timeout bugs related to accessing iOS ports which hampered development for a small amount of time, but overall, I could connect to the devices and access the console to debug my functions.

There was one issue I had with the debugging process: inability to inspect an element by tapping on it. That is beneficial to my styling capabilities as a web developer. Updating styling without it delivers nothing more than an adequate experience.

React Native

React Native supplied a very similar experience from a debugging standpoint. I could log functions and test certain functionality adequately, but the device to element interface is lacking. However, since React Native allows a smoother transition to percentages (see responsiveness section) this didn’t create a significant problem.

Continuous Integration

Nativescript

Documentation regarding continuous integration and automated build processes with NativeScript are very few. The NativeScript community uses a single blog post as a reference point for learning about how to troubleshoot build and release processes with NativeScript. In this specific example, the author utilizes TeamCity and automates the Android-only build and packaging.

Upon speaking with the mobile team lead, all of the company’s mobile build processes are automated but hosted and maintained in-house at another office. NativeScript is compatible with this approach, and all processes can be automated if the Android/iOS runtime versions are compatible with the installed development kit versions.

React Native

React Native’s build processes parallel NativeScript’s approach but is much better documented. Utilizing either the React Native or Expo CLI, the build pipeline can also be automated using the build:ios and build:android commands for iOS and Android, respectively.

Running yYour App – Emulators and Device Management

Emulators
iOS

Due to Apple’s privacy and OS-specific technologies like XCode, the only options for debugging and building an actual iOS application is if you are running on a Mac. XCode has an extensive emulator that has every iOS device form factor.

Android

https://docs.nativescript.org/tooling/android-virtual-devices

There are three ways to run a Nativescript application that has been developed:

  1. Via a connected device
  2. Via an android emulator – Android Studio has a built-in emulator
  3. Via a third-party emulator
Local Device Testing
Nativescript

Local device management and testing can be completed either via the CLI or with NativeScript Sidekick. iOS and Android devices are connected via USB and have LiveSync capabilities so any code change within a NativeScript project triggers a local build that updates the application within seconds.

CLI
tns device

Lists all recognized connected physical or virtual devices.

tns device run

Runs the selected application on a connected device

Sidekick

 

 

React Native

By default, any React Native app that is built with the Expo CLI is not initially packaged as a standalone app, contrary to NativeScript. First, developers are required to eject the application to ExpoKit (native iOS/Android library that allows developers to use Expo). Next step is to run expo build:ios or expo build:android for iOS and Android builds, respectively, and with a successful build the CLI will generate the corresponding packaged file for each platform.

From there it is broken down into platform-specific instructions, as each platform needs a specific configuration for running on a device. The documentation for that is here.

Platform Tools

NativeScript has its own platform tools, while React Native has deprecated its own CLI and tools in favor of a partnership with Expo. Below is a checklist and review of the features that each framework toolset provides.

Nativescript
Desktop GUI
CLI
Cloud Builds for iOS and Android packaging ✓*
Browser-based code editor
Wireless Debugging

 

*First 100 cloud builds are free, any after that require a monthly subscription. See rates here

NativeScript Sidekick (Desktop GUI) – This is NativeScript’s hub for application management. In this GUI developers manage connected devices, build packaging processes, plug-ins and more.

NativeScript CLI – Command line alternative to Sidekick.

https://github.com/NativeScript/nativescript-cli

NativeScript Playground –NativeScript’s browser-based code editor and client application for iOS/Android.

Expo
Desktop GUI
CLI
Cloud Builds for iOS and Android packaging
Browser-based code editor
Wireless Debugging

 

React Native building, packaging, release and debugging all rely on a technology called Expo. Expo maintains a suite of products – Client, CLI, Snack, ExpoKit, and SDK. React-native’s partnership with Expo has given developers an entire framework to assist with device management, testing and debugging.

Expo CLI – React Native used to have its own native CLI to create and manage project and connected devices. As of their recent partnership with Expo, React Native has shifted its CLI processes to Expo and deprecated both create-react-native and react-native commands in favor of Expo’s CLI. My experience with the CLI has been very mixed. Configuration was one of the most drawn-out processes in any framework set up that I have ever implemented. Due to the fact that Expo recently deprecated its desktop application XDE in its 30.0.0 release, the GUI for React Native device management and debugging has transferred over to an in-browser debugging tool, hosted locally on a server. This is helpful, but also significantly more difficult to configure because each developer needs to configure his/her proxy to tunnel through Localhost:8888 which is a liability with corporate firewall and proxy policy.

Expo Client – React Native’s alternative to NativeScript’s playground application. As a free app in the App and Google Play stores, it allows any iOS/Android device to wirelessly run the application via QR Code (Android only) or via a link to a hosted server.

Snack – Browser-based code editor where you can run your application wirelessly.

ExpoKit – ExpoKit is an Objective-C and Java library that allows you to use the Expo platform with a native iOS/Android project, preferably with React Native. See the React Native section of Local Device Testing for a little bit more context on this.

 

Summary

The companion tools that accompany both React Native and NativeScript are similar, but this is an area that is very dependent on what operating system you are using. For Windows development, one important question that needs to be asked is:

“Can you truly develop for RN/N on any operating system?”

And my answer to that is: “Not realistically”.

As noted above, NativeScript possesses the ability to build to the cloud when packaging your .ipa and .apk files that will run on the device. This functionality was very helpful when building a simple prototype application. However, that seems to be the extent of its helpfulness, as NativeScript charges developers a monthly rate if they surpass 100 cloud builds a month. Due to that subscription model, this would end up being a costly approach compared to React Native when implemented at an enterprise level. I also foresee potential iOS-specific device and build issues that can only be solved by accessing the build files on a macOS device.

The alternative to cloud build packaging is to build locally. Both incorporate well with Xcode and Android Studio and can achieve that functionality equally. However, this is only achievable when developing on macOS (sorry Windows/Linux users).

Access to Native APIs

Both React Native and NativeScript utilize a plethora of plug-ins in order to access native libraries and common functionality. In NativeScript, the plug-ins are built in JavaScript and compiled into the Native APIs using JavascriptCore and V8 runtime engines for iOS and Android, respectively.

Maps
NativeScript
NativeScript plug-in

NativeScript supports Mapbox, Google Maps, and even native app map applications very efficiently. For the prototype application, I used Mapbox to ensure that the map technology on the existing application is supported in NativeScript. I utilized the well-documented nativescript-mapbox plugin and it was very simple to use.

React Native

React Native also utilizes an easy-to-use plugin for Mapbox but requires an import to local build files to get it to work.

 

Camera
NativeScript
Plug-in

NativeScript utilizes an open-source plugin to access the camera application and take photos. Displayed on the prototype application. Very easy to implement and use. Functionality requests camera and photo permissions and then opens the camera application.

React Native
Plug-in

React Native also supports a multi-functional plug-in for camera functionality. This plug-in also needs to be imported into the build files so that it can work.

 

Notifications
Nativescript
Plug-in ✓*

*push notifications via cloud messaging requires a third-party

For the prototype, I implemented push notifications by using a local notifications plugin. This was a very simple process, all that it required was installing the plugin in the project package.json, importing it, and utilizing a function.

React Native

React Native also utilizes a plugin to send local and cloud push notifications, but it accomplishes this with a bit more time-consuming approach than NativeScript. The actual implementation of the notification is similar, but React Native developers need to register with Apple first in order to send a push notification.

This extra step can either be accomplished by editing the iOS App’s AppDelegate.m file and importing the notification plug-in or manually registering for notifications in XCode, both of which require a macOS device to complete. The plug-in also requires edits to Android’s build.gradle file in order for it to work on the Android side.

 

Local Storage
NativeScript
Plug-in

NativeScript’s plug-in uses a third-party plugin created by a well-known NativeScript contributor for its local storage capabilities. The plug-in possesses six functions to read, write and access local storage for your NativeScript application.

React Native

React native has a framework library called AsyncStorage that is used with the new await/async functionality in JavaScript to store and fetch data.

Responsiveness

NativeScript

Responsiveness has a few obstacles in NativeScript. The built-in functionality is to create different XML or CSS files for each form factor (mobile/tablet) and style it from there. However, that screen size qualifier approach is not compatible with Angular and Webpack builds due to Angular’s AOT compilation.

https://docs.nativescript.org/ui/supporting-multiple-screens#screen-size-qualifiers

As of September, NativeScript doesn’t have built-in CSS media queries. A few different plug-ins have been implemented to try and fix this and there are some hacks available, but it is an additional challenge.

https://github.com/NativeScript/NativeScript/issues/64#issuecomment-420757100

However, there is an available plugin that mocks the CSS media query functionality. The plugin allows you to define platform-specific styling using .ios or .android prefixes on any class and also manages to (a bit clumsily) prefix device size in terms of dpi (.ios1024 .android680)

From there, I ran into a few issues implementing the plugin. I felt that it created too much rework to implement it when I had already established a project file structure. EddyVerbruggen, who is one of the top minds in the NativeScript community, suggested this workaround and I implemented a similar solution. The premise of his solution utilizes the NativeScript device interface which has os, deviceType and model properties which assist in building cross-platform or form-factor.

React Native

React  Native seems to have a much more comfortable implementation of device and platform responsiveness. Although React Native doesn’t fully support applying percentages to CSS properties, there is a package named react-native-response-screen that allows developers to convert percentages to dependent pixels.

A second React Native library named react-native-responsive give developers the full capability to implement Media Queries throughout platform and device form factor, rounding out the responsiveness capabilities of React Native as a whole.

Compatibility

NativeScript

Since NativeScript is built to be used with Angular, it is important to note its backward compatibility with the Angular framework. Via this NativeScript contributor, NativeScript supports Angular 2+ and has no intention of supporting Angular 1 in the near future. NativeScript supports all recent JavaScript versions and versioning can be changed very simply.

React Native

From the standpoint of React/React Native compatibility, there is nothing significant worth nothing. Both are developed and maintained by Facebook and don’t have to deal with the same compatibility issues that Angular/NativeScript have to deal with as separately owned frameworks. React Native as a framework supports all recent JavaScript versions and versioning can be changed by editing a single line of code.

Completeness of Platform

Community

One of the most important factors in a quality framework is its community. Usage, issue management, and consistent updates are imperative for a framework to be a successful and sustainable investment. Here is a break down of the statistics surrounding the NativeScript and React Native communities, respectively:

Github
NativeScript

Stars: 15.1k

Forks: 1.1k

Contributors: 119

React Native

Stars: 69.8k

Forks: 15.7k

Contributors: 1,761

Over the course of the project, I submitted issues to both NativeScript and React Native repositories, and I received a quick response from contributors in each situation. However, the most glaring difference in the communities is in the volume of issues submitted. Due to React Native’s maturity and larger adaptation, when I encountered an issue and I searched StackOverflow, Github, internet forums, etc. for an answer there would be three or four different people who had the exact issue or a similar one. Due to this, I saw multiple potential solutions and determined which one was the best remedy for my problem.

When I encountered an issue with NativeScript, I would find a similar question asked only once on either Stack Overflow or the NativeScript forums and at times a speculative answer would be given instead of a verified contributor answer which led to further investigating on my end. This could potentially be a point of concern, but not definite. Although the smaller developer community required me to research further, I developed a deeper grasp of the framework in doing so.

Learning Curve and Skillset reuse
NativeScript

For developers who have an Angular/JavaScript background, this makes the learning curve for both platforms much simpler than if someone was starting from scratch. Given that premise though, I see Nativescript being much simpler of a transition due to when paired with Angular, the only differences between building a Nativescript native application and an Angular-only web application is essentially the template. With an Angular web application, you utilize HTML for the template, but Nativescript uses XML and its own built-in native UI components.

Project and folder structure, development language and testing framework are all the exact same as an Angular web application, nothing on that end of the application changes when utilizing NativeScript.

React Native

The learning curve for React Native is significantly higher than for NativeScript, especially for those with an Angular background. Although the framework isn’t difficult to pick up, there are fundamental differences in how common functionality is implemented in JavaScript. Here are a few examples:

JSX – instead of separating JavaScript functionality into a component and view functionality into a template, React Native accomplishes this all in one file that possesses somewhat of a mix of the two.

Styling – All styling is treated as a JavaScript object and syntax is slighting changed due to that. The style object is also included in that single JS file along with the view/component functionality mentioned above.

However, developers with an Angular background will be familiar with basic JavaScript/TypeScript functionality and will be able to pick things up quicker in React Native than for a completely new development language.

Code Reuse

There are many things to look at when considering JavaScript-native frameworks like React Native and NativeScript. For an investment into one of the technologies to be fruitful, it needs to have a net positive impact on the developers, code base and performance of the application. For any Angular 2+ application, NativeScript is an easy transition with a significant amount of reused code and framework knowledge. However, for an Angular 1 application, the transition would be a similar amount of work as transitioning to a new framework like React Native due to the amount of code rewriting. Since NativeScript doesn’t support Angular 1, the application would need to be upgraded to Angular 2 which would contain a significant amount of rewrite.

On the React Native side, there would be no existing code reuse because the development team would be implementing an entirely new framework. Feature implementation would take on a different approach due to the way that React Native focuses on separation of concerns.

Share this:

Leave a Reply

Your email address will not be published. Required fields are marked *