These are good questions.
Let me start with some of the most important principles that guide the NativeScript project.
In NativeScript, we leveraged Telerik’s experience creating productivity tools for developers to create a framework for building cross-platform native mobile apps that any developer can quickly pick up and use. From the beginning, NativeScript has focused on delivering a solution that should:
These principles guide the architectural decisions that we make as NativeScript evolves. Let’s take a closer look at how these principles have driven our decisions around threading.
This is a powerful capability, and unique, even among alternatives like React Native and Fuse that require native code plugins and new layers of abstraction to interact with native APIs.
There is a time and a place for background threads, but putting all app code on a different thread from the UI by default clearly affects the efficiency of calling native APIs.
Yes and no.
First, for those not aware, “dropped frames” are the result of the UI thread being too busy to deliver smooth, 60fps refreshes. When an app begins to drop frames, the UI “stutters” and introduces what many developers now call “jank.” It’s an all too common problem in hybrid apps, and a big reason we created NativeScript in the first place.
An example of how fast, fluid and responsive apps built with NativeScript are is our marketplace demo:
A quick teaser for those who love CSS – the animations on this screen are entirely made via CSS
Not coincidentally, this is the exact same problem you’d encounter creating “raw” native apps for iOS or Android using Obj-C, Swift or Java. By default, native code runs on the same thread as native UI, so CPU-intensive operations in native code can also degrade app performance and cause dropped frames.
NativeScript, true to its billing, is behaving identically to native apps.
It follows, then, just as in native apps, the correct solution is to selectively offload CPU-intensive code to background threads so that animations and other UI-related code continue to run smoothly. True in native apps. True in NativeScript.
NativeScript started by focusing on creating a fast and powerful single-threaded native API access layer that would deliver smooth, high-performance UI for the most common app scenarios. As discussed above, we’ve focused on minimizing marshalling and creating a runtime that behaves very similarly to native apps.
Now that this layer is stable and performant, the next step is to add the background thread APIs to enable selective offloading of the most CPU-intensive tasks.
“Wait? I thought you said background threads were NOT in NativeScript today.”
As it turns-out, most use cases for background work are not often associated with application-specific code. They are generic use cases and usually involve http or network requests, database access, image decoding and processing, heavy IO operations and so on.
For a significant number of these scenarios, NativeScript modules and plugins already exist to do the generic work on a background thread, dispatching the output to the main UI thread when the heavy lifting is done. The out-of-the-box HTTP module, for example, uses a background thread to process network requests, as does the push-notification plugin available on NPM.
Of course, there are still uncovered scenarios when you may need to utilize a background thread for generic CPU-intensive work.
That’s today. It’s an advanced approach, mostly intended for plugin developers.
For the “typical” NativeScript developer, we still want to provide an API that makes it possible to do arbitrary work on background threads in a cross-platform way without writing native code. Think: “Web Workers” for NativeScript. So let’s look at what’s next for background threads in NativeScript.
So, what have we learned?
Header image courtesy of Marlon M