Tag Archives: NativeScript

NativeScript, Master Technology, ProPlugins, and nStudio.

So since this question has come up multiple times; I decided to write a brief history of my involvement with NativeScript, Master Technology, ProPlugins, LLC and nStudio, LLC.

So this story begins a little over 5 years ago; I had been doing some Cordova/Phonegap development on a simple application for my wife; and its performance ended up being sub-par, ran into screen sizing issues, and a whole myriad of the common standard issues you run into with programming for a webview. Most these hybrid issues are much better now. At that point -- frustration was enough to make me decide to see if their was anything better.

I downloaded a huge number of platforms, React Native, Titanium, Fuse, Xamarin, you name it; I found a link to it I downloaded it and tried it out. After spending multiple days installing and testing things, I finally decided to using React Native -- it was the best of the bunch. A few days later I saw a article on a news site; saying checkout something called NativeScript. I figured, might as well -- I wasn't totally sold on React-Native and I hadn't started my project.

So I downloaded NativeScript v0.90 or v0.91, which was the first official "open" release in early March of 2015. I totally fell in love with it. It has a good template syntax, data binding and best of all full easy access to the entire native platform all using JavaScript. It really was the "perfect" mobile development system.


Now as to Master Technology, it was started a long long time ago, in a galaxy far far away... Almost 30 years now... So basically, in a nutshell this was the company I did all of my contracting work under. As such, when I started doing NativeScript work I continued to do all of my work under it. This is why you see a large number of plugins and NativeScript related sites with the Master Technology logo. One of the first, https://plugins.nativescript.rocks, started as a simple MD file on github...

However, that soon became unworkable when the community started adding multiple new plugins a week. So I created the first version of https://plugins.nativescript.rocks... From there images, searchcode, compatibility chart and many other community resources have been added...


After a couple years of working in the NativeScript community, I realized that as a sole contractor it was very hard to handle larger jobs by myself. In early 2017, I had the brilliant idea to start a company that would be more like a law firm, with senior and junior partners but geared for developers. I enlisted my co-owners Brad Martin, and Nathan Walker and we created a brand new company called nStudio in early 2017. From there we grew a bit, to the point we even added a new co-owner in 2019, Dave Coffin. We continued to grow adding several partners known highly in the community to our team like: Igor Randjelovic (NativeScript-Vue), Osei Fortune (author of many awesome plugins), Alex Ziskind (the tutorial master of NativeScripting.com). In addition we have developed strong ties with many other companies in the greater developer eco-system.

When any new NativeScript clients would contact me, I move them to nStudio. Any other clients (Servers, PHP, Clarion, Node, etc) stayed on Master Technology as that company is now more oriented to server side stuff, and nStudio was for all the mobile development.

One strange thing about having two companies is dealing with IP, so any IP that I had developed at Master Technology, remained with Master Technology. You will still see Master Technology on a LOT of sites and plugins in the NativeScript eco-system even though Master Technology only does a small amount of work in the NativeScript eco-system now.


In early 2019; as still one of the major open source plugin NativeScript developers; I realized that NativeScript community needed some way to fund plugin maintenance. We were seeing a great number of plugins that were not maintained and no longer working. The maintenance time on my own plugins, that were free to the community, became far too excessive for me to be able to keep them to a standard I'd be happy to have my name on, and still be able to feed my family. I got together with several other large plugin developers and we started ProPlugins, LLC. This has helped at least with a chunk of the plugins under our control; and so ProPlugins, was founded and is owned by Master Technology.


Now comes the most interesting turn of events in this entire story, one that I would NEVER have expected in a million years.

Because of NativeScript, I helped found two additional successful companies. Which just by itself is totally awesome! However, now nStudio, LLC has been able to purchase NativeScript and its assets. We now have control over not only our companies future, but the framework that was directly responsible for spawning nStudio, LLC.

As such, you should now see my name (and the other partners from nStudio, LLC) on the all the new pull request approvals and reviews for NativeScript. I do want to sincerely thank all the developers over the last 5 years who actually built NativeScript, and if any of you want to continue to work on the framework, please feel free to drop us a line at team (@) nativescript org.

(c) Adam Carter, https://www.flickr.com/photos/44811338@N05/7505286308

Optimization Gotcha's for for/i and forEach

So I mentioned something on my interview with Alex of NativeScripting.com that he did with me. And someone asked about this in the comments, so I decided to create a blog article on this specific optimization tip.

I am going to code this to a browser rather than in NativeScript because well JS in a browser is just plain easier to show the memory issues because you can plop the code in to a new browser tab and step through the code instantly. 🙂

<html>
<body><div id="stacklayout"></div></body>
<script type="application/javascript">

// Pretend Color class to be similar to NativeScript
class Color {
    constructor(val) { this._color = val; }
    toString() { return this._color; }
}

const <strong><em>colors </em></strong>= ["#ff0000", "#00ff00", "#0000ff"];
for (let i=0;i&lt;<strong><em>colors</em></strong>.length;i++) {
    const labels=["Wow","Awesome","Interview", "Alex", "Created!"];
    for (let j=0;j&lt;labels.length;j++) {
        const clr = new Color(<strong><em>colors</em></strong>[i]);
        const txt = <strong><em>document</em></strong>.createElement("div");
        txt.innerText = labels[j];
        txt.style.backgroundColor = clr.toString();
        const parent = <strong><em>document</em></strong>.getElementById("stacklayout");
        parent.appendChild(txt);
    }
}
&lt;/script>
&lt;/html>

And you should see something like this:

We are repeating the labels for each of the primary colors...

Or you might be used to doing something like this instead:

&lt;html>
&lt;body>&lt;div id="stacklayout">&lt;/div>&lt;/body>
&lt;script type="application/javascript">

class Color {
  constructor(val) { this._color = val; }
  toString() { return this._color; }
}

["#ff0000", "#00ff00", "#0000ff"].forEach((clr) => {
  ["Wow","Awesome","Interview", "Alex", "Created!"].forEach((word) => {
     const txtColor = new Color(clr);
     const txt = <strong><em>document</em></strong>.createElement("div");
     txt.innerText = word;
     txt.style.backgroundColor = txtColor.toString();
     const parent = <strong><em>document</em></strong>.getElementById("stacklayout");
     parent.appendChild(txt);
  });
});

&lt;/script>
&lt;/html>

Both have several issues, however the second one can be vastly worse than the first one depending on how many iterations. So lets walk through the issues.

So the Color class is fine, we are using it to show creating objects... So just ignore it for now.

const <strong><em>colors </em></strong>= ["#ff0000", "#00ff00", "#0000ff"];
for (let i=0;i&lt;<strong><em>colors</em></strong>.length;i++) {

These lines are fine, we allocated colors, then looped through them. So far so good. Lets proceed, what about:

const labels=["Wow","Awesome","Interview", "Alex", "Created!"];

Well here is the first issue; Fortunately for us, the v8 JS engine actually pre-allocates the 5 different string "Wow" through "Created!" when it parses the JavaScript however, each loop through it does create a brand new Labels array and then links those strings into it. So in this case it is small overhead; however in the 3 loops that still is 2 more sets of allocations and all new GC enties that have to be cleaned up after the loop is completed. If you were to put this single line of code outside the loop; your code runs the same, but no less memory usage and less processing.

 const clr = new Color(<strong><em>colors</em></strong>[i]);

What about this line, well in this case all 15 times it creates a brand new Color object. You can easily make this only be ran 3 times just by moving it outside the inner for (j) loop into the for (i) loop. In this example the Color class is very light weight. But many classes you create inside loops will be very heavy with lots of allocations going on when you allocate the class. So pay attention, 3 allocations vs 15 allocations, all by putting the line in the wrong spot...

Continuing on, most the rest of the lines has to be inside the loop; but I tossed another item into the loop, that wasn't needed... This line is very easy to accidentally end up in the loop because you needed it at that point.

     const parent = <strong><em>document</em></strong>.getElementById("stacklayout");

Yep, this has to do an expensive lookup in the dom to find this element, it never changes. It also has to allocate it to that "parent" variable 15 times. If you dropped it before/outside of both loops, you would have a single lookup and allocation...

---

Finally lets look at the last example; it suffers from the same issues. However, this one I used a Array.forEach rather than the simple for (i) loop. Why do I say it can be worse then? Well in small numbers, the difference is actually pretty tiny. The extra amount of memory it uses over a for (i) loop is also reasonable. But in larger loops (especially loops inside of loops inside of loops); the difference can end up being exponentially larger.

Your creating and calling functions, and all those functions now has added scopes and the engine has to setup all the callstacks for each and every iteration, additional error checking and just plain running a lot more code behind the scenes. So what is a simple for (i) loop in the first example, now became 15 EXTRA functions calls with all the extra overhead of cpu and memory that entails. Again in small chunks they are perfectly fine, but if you are wanting performance, every ms and gc adds up and sometimes they can add up very quickly when dealing with the Array helper functions that use callbacks...

As a better way to phrase this; imagine you have a for (i) loop that takes 5ms and a forEach loop takes 25ms to finish. Both are still dang fast, hard to even benchmark. But now you embed it in another forEach that also by itself takes 25ms. 25ms * 25ms = 625ms. More than half of a second. But, if you were to switch this to a for (i) loop each of them is 5ms. So, 5ms * 5ms = 25ms. Both are exponentially larger, but 25ms vs 625ms and the difference starts becoming much clearer. Now add a third loop; 5ms*5ms*5ms = 125ms. 25ms*25ms*25ms=15,625ms (or > 15 seconds!) In small chunks the time and memory used from a forEach is minuscule. But depending on how many times it is called; it can add up very quickly to be a major difference.

Please note this goes for all the nice Array helper functions, .map, .reduce, .filter, etc. Everyone of them that uses a callback, has somewhere between 2 times and 50 times as much overhead as a simple for (i) loop. Remember, despite this overhead; these functions are extremely fast. So don't be afraid to use them, but be more wary of using them in deeply nested code that can easily be called in loops when the datasets they are working against are also large.

As many items that you can actually move outside of your loop, the better off you are. This Includes any expensive calculations! You might be able to do 99% of the expensive calculation outside of the loop; and then finish off the last part of the calculation inside the loop...

I hope this answers the question about loops and performance. Every loop is a golden opportunity to greatly enhance your app,

NativeScript Fonter revisited again (using DuoTone FontAwesome)

In a prior post I discussed using fonts in NativeScript. This morning I saw an issue in the NativeScript github repo about how to use the Font Awesome Duotone fonts.

Since I love puzzles, and I know the NativeScript font system fairly well, and I also own a subscription to the commercial Font Awesome -- I figured I could easily see if I can make it work. Immediately, I had a idea on how to solve the issue.

So I downloaded both the WebFonts and the Desktop fonts. Interestingly, enough the Desktop fonts actually have a warning that links to a post about Duotone fonts and the issues with the desktop... So after I read that post; it basically confirmed my understanding on how this font works and exactly how to make this work inside NativeScript.

So first things first, you need to update your app.css file; you want to add something like this to it:

.fad {
   font-family: fa-duotone-900, Font Awesome 5 Duotone;
   font-weight: 900;
}

.fad-op {
   opacity: .4;
}

Why TWO names for font-family?

If you recall from my prior fonter post; you want to create the rule that has the name of the actual font file without the .TTF or .OTF extension. So since the font folder looks like this:

The last file in the example fonts folder, is fa-duotone-900.ttf; straight from the web download zip file that I downloaded this morning.

So you see the rule is:

   font-family: fa-duotone-900, Font Awesome 5 Duotone;

This allows NativeScript to find the actual file name, in a lot of cases it can use just the filename to work its magic. However on iOS specifically, we want to include the actual internal font name. So double clicking on the font gives us this image under linux.

Under macintosh the title bar also shows the exact same information. So that is why I then typed "Font Awesome 5 Duotone" as the second part of the rule -- this must EXACTLY match. The two names covers all the cases we need, font file name to load it and actual internal font name to reference it later.

The second css rule we just added was fad-op, it is so that we can have some opacity for which ever section of the font we want or need opacity on.

We can do no opacity, solid/solid, and it would look like this:
Notice both parts are solid.

Now if we add opacity to section two; you can see the beak, legs on the bird are slightly transparent; and the acorn body is partially transparent.

Finally if we reverse the opacity to make section one have the opacity it looks like this:

You can also apply any opacity you want like 0.10 looks like this

And you can apply opacity to both sections and it looks like this:

All of them are using the EXACT same colors; just a difference in opacity. The sky is the limit; you are free to color and apply opacity on whatever amounts to each of the two sections.

So how do we do this magic?

Well technically the hard part is already done, that awesome css rule and dropping the font file into the app/fonts folder has 99% of the work done for us. The rest is simple stuff.

So the next thing you need to know is; which duotone icons do you want to use?

So first we need to know what is available for duotone; so we go to the font awesome icon page; and select the duotone filter. Once we have that; we can choose something; so lets look at the crow.

The crow at the top of the page lists this information:

Now at this point we can't really use "fa-crow" just because NativeScript doesn't know what that is; but the two pieces of information we do need to know to make it work is the f520 and the 10f520 these are the unicode values for the two sections of the icon we want.

So our xml needs to look like this:

 
  

This gives us the two characters in the same location on the screen. The first character is using the "fad" css rule; along with the text color blue. The second character is also using the "fad" css rule, and it adds the red text color and the "fad-op" rule for opacity.

Which gives us the duotone bird:

The key item is that you want the characters to print over each other; Gridlayout by default allows you to put multiple items in the same row and column. Since the characters are the same size; they by default will automatically line up and work.

Angular Flavor Issue

Angular's HTML parser has an issue which characters in the upper unicode -- it is great with any unicode value 65535 and below. Which of course if you have seen the first character of each of these duotone values is < 0xffff (65535). However the second character starts in the 0x100000 (1048576) range which is a lot larger than 0xffff. Unfortunately this means that in Angular even though you pass in 0x10f520 you actually get 0xf520 assigned. If you are paying really close attention, this is the same value as the very first code. So in angular you get two labels with the exact same unicode value. So how do we fix this?

Well ultimately; the underlying Angular parser should be fixed -- so if one of you wants to tackle this, track down where in the parser it breaks and push a PR; that would make a lot of people in the Angular community happy! However, since this is not something I am going to tackle and I still want you to be able to use Duotone fonts, I will present an alternate method to how to fix this on Angular.

In Angular; we can do it one of two ways; automagically; or direct assign. I prefer the automagically; so this is the HTML that we have:

<Label col="1" text="&#xf6ae;" class="larger fad "></Label>
<Label col="1" text="&#x10f6ae;" class="larger fad blue fad-op" (loaded)="fixAngularParsingIssue($event)"></Label>

As you can see it is identical to the above NS-Core XML, except I added the (loaded) event. This event fires once in the lifecycle of the Label. And runs my handy dandy "fixAngularParsingIssue" function.

fixAngularParsingIssue(args: any): void {
  let field = args.object;
  let val = field.text.codePointAt(0);

  // Check to see if this is already a valid unicode string above 0xffff.
  if (val > 65535) { return; }

  // We found a character we need to change...
  val = val | 0x100000;
  field.text = String.fromCodePoint(val);
}

The function is straight forward; we grab the current text value; verify it is actually still less than the unicode value we want as the parser could get fixed in a future version. Then we take that value and add our missing 0x100000; and then re-assign the text. Now this function could instead be written to take the actual value you want to assign rather than computing it, but I prefer simplicity as then I can just add this function to all labels that need it and just not think about it.

Angular Directive

I suggested in the issue that someone create a directive; and Pandishpan spent the time and converted my simple code into a directive for Angular making it even easier to use in angular! Thank you for your awesome work! So now, all you have to do is apply the "labelDuoTone" directive to the html, and it handles the rest of the work for you.

You can grab the code for the angular directive in the github issue here.

NativeScript Core demo application

You can download the NativeScript-Core fonter application from the github repo, https://github.com/NathanaelA/fonter

Please note the fa-duotone-900.ttf font is NOT shipped with the demo; you must download it yourself and copy it into the app/fonts folder.

Android (on left) and iOS (on right) looks like this:

Android
iOS


NativeScript 6.4 released

NativeScript 6.40 has a couple cool new things; but better yet it fixes several issues that can will affect your users if you are using 6.3.x lets look at them...

Some of the fixes include instability during android's fragment handling occurred in 6.32, which is worth while. A couple really awesome community PR's, and of course one of my favorite items is the new CSS parser by default and the v8 upgrades...

[UPDATE] The new 6.4.1 Android engine that was just released a day or so after 6.4.0 adds v8 version 8! Which add a lot of cool features (see v8 section)

Core Modules

  • NativeScript is got a new much faster CSS parser in v6.3 -- it is now default in 6.4!
  • The community (Ryan & Hamdi) and the NativeScript team worked on 3d rotation for a while now; this has now shipped! .rotate-x, .rotate-y, and .rotate-z
  • .Fixed background color reset on Tabs

We had even more awesome community PR's this month, a big thank you to the community!

CLI

The CLI team has fixed several outstanding bugs; including several webpack hmr issues. This also includes Node 13 and Android API 29 compatibility.

  • CLI now cleans up after itself in a corner case where CTRL-C'ing when first starting the build.
  • Doctor now will throw error if using Java 13 (NativeScript doesn't support it yet)
  • CLI Will now detect and let you know about the breaking issue of including multiple versions of the same plugins or multiple NativeScript core versions.
  • Native Metadata filtering, allow Application/Plugins to declare what Metadata they need; to allow smaller metadata and faster startup.

Webpack Changes

  • Snapshot bug fixes
  • Ability to set a Webpack config location so you can add custom application rules
  • Ability to allow custom platforms building (--env.platform <platform>)

V8

If you didn't read my notice on the last update; I'm creating this new v8 Section, because Android and soon iOS will both be using the same v8 engine. v8 was upgraded to v7.9 (in 6.4.0) and then the awesome v8.0 was slipped into (6.4.1) which adds:

  • IC Handlers are now cached properly; giving a ~12% for all IC calls into the C++ runtime.
  • OSR Replacement - 5% - 18% speed up.
  • Pointer Compression (Saves up to 40% of heap memory) which increased speed on large JS by a few percentage points!
  • Optional Chaining
  • Null coalescing

Android

  • Async WebAssembly issue resolved
  • Memory freed on some objects that were being retained
  • Upgraded to V8 8.0 (See v8 section)
  • Fix for Elevation usage on some API versions
  • "FlipRight/flipLeft" transition fixed

IOS

  • The CLI will warn you if you forget a module.modulemap file in your included .M files
  • Project Template is FastLane compatible
  • Fixed discarded exceptions
  • Safari Inspector now shows startup errors
  • A lot more changes to the new v8 version of the iOS runtime that is now in BETA testing to eventually replace the JSCore version... Overall now is the time to test it!

Updating NativeScript

To get updated; you first need to do:
npm i -g nativescript@latest

To update a project; you need to do the following:

Latest Runtimes:
tns platform remove android && tns platform add android@latest
tns platform remove ios && tns platform add ios@latest

Latest Core modules:
npm r tns-core-modules --save
npm i tns-core-modules@latest --save

To install Webpack support:
npm i nativescript-dev-webpack@latest --save-dev

To install latest NativeScript Angular plugin
npm i nativescript-angular@latest --save
You will then need to install the actual angular bits; which as of this post v6 is currently supported.

The addition of t additional analytics/tracking to the CLI reminded me; you can disable it permanently; if you value your privacy by doing:
tns usage-reporting disable && tns error-reporting disable

NativeScript 6.3.0 Released

NativeScript 6.30 has a couple cool new things; but better yet it fixes several issues that can will affect your users if you are using 6.2.x lets look at them...

Some of the fixes include instability during android's switching of applications and resuming it. An issue with unloading views on Android. Out of memory situation on Android, and dialog fixes for iOS. In addition to several important build fixes that appear to solve a lot of build HMR related issues. Overall this release is worth upgrading to for just the bug fixes alone.

Core Modules

NativeScript is getting a new CSS parser; unfortunately it is not enabled by default in 6.3; but based on a PR should be enabled by default in 6.4. If you would like to enable this in your app to see how much faster it can parse your css; you do so by editing the packages.json file that ships with the application and adding a new key called "cssParser" and set it to "css-tree". The valid options are "rework" (current parser) and also "nativescript" which was the original css parser.

We had a couple awesome community PR's this month the first by Eduardo Speroni adds requestAnimationFrame as a supported function. And the second by Shailesh Lolam  add dialog sizing (width & height properties) to the modal dialogs on iOS.

And finally to round up our new core module features; Modal dialogs now have all the same CSS properties applied to them to allow better styling. In addition to the normal properties, a new .ns-modal class is applied.

CLI

The CLI team has fixed several outstanding bugs; including several webpack hmr issues. This also includes Node 13 and Android API 29 compatibility.

V8

I'm going to create this new v8 Section, because Android and soon iOS will both be using the same v8 engine. v8 was upgraded to v7.8 which adds:

  • Faster object destructuringconst {x, y} = object; This is now as fast as the normal ES5 const x = object.x, y = object.y;
  • Lazy source positioning; which can save 1 - 2.5% of memory; basically instead of storing all source code lines for when errors occur; it recalculates it when it needs it.
  • Faster RegEx
  • Several Wasm improvements

Android

The Android team kept busy this month;

  • Fixed some Kotlin issues
  • Android Signal 1 & 11 are now captured
  • Fixed a worker issue
  • Upgraded to V8 7.8 (See v8 section)

IOS

  • Upgraded to WebKit 13.2
  • Several metadata fixes
  • Fixed a worker issue
  • Fixed debugger not working issue
  • Fixed discardUncaughtJsExceptions issue

    A lot of changes to the new v8 version of the iOS runtime that is still in alpha testing to eventually replace the JSCore version... It appears the iOS v8 version is shaping up to be an awesome release.

Updating NativeScript

To get updated; you first need to do:
npm i -g nativescript@latest

To update a project; you need to do the following:

Latest Runtimes:
tns platform remove android && tns platform add android@latest
tns platform remove ios && tns platform add ios@latest

Latest Core modules:
npm r tns-core-modules --save
npm i tns-core-modules@latest --save

To install Webpack support:
npm i nativescript-dev-webpack@latest --save-dev

To install latest NativeScript Angular plugin
npm i nativescript-angular@latest --save
You will then need to install the actual angular bits; which as of this post v6 is currently supported.

The addition of t additional analytics/tracking to the CLI reminded me; you can disable it permanently; if you value your privacy by doing:
tns usage-reporting disable && tns error-reporting disable

ProPlugins - end of year update

We started the ProPlugins project pretty close to the launch of NS (NativeScript) 6.0. So it has only been active for about five months now. So how is it doing???

Well, first let cover the reason why we created it. This plays in strongly into how well ProPlugins is doing.

Why ProPlugins?

For most of us plugin developers who have worked in the NativeScript eco-system for a while. We all knew that NS 6.0 had a range of breaking changes; which meant it was the fifth set of breaking changes in less than 4 years for plugins. Each one of the NS major releases, had a range of breaking changes that required certain types of plugins to make fixes. Sometimes the changes were minor, other times the changes actually requires some major rewrites and/or major time debugging why something was no longer working properly. Of course the vast majority of this work was done by the original author; with very little or no help from the rest of the community. I recommend you read all three of my prior blog posts on the plugin costs and the plugin problem. And then why we believe ProPlugins is the solution. With those posts you will have a pretty good idea that the actual costs to an author, the community involvement, and how the open source seems pretty much unsustainable.

In addition to our experience, their are lots of blog posts by many other authors, on how for the most part, the majority of projects that are open source by independent developers has a serious funding and/or burnout issues. We have seen the exact same thing in the NativeScript plugin community way too many times. in fact, the other day I responded to a issue saying that I believe a specific plugin was still maintained as this author has been around for a while -- and then several people pointed me to the issue where the author has mentioned it is no longer maintained. Sadly another excellent plugin author appears to have left the community.

Community Involvement

When we FORKED all these plugins into ProPlugins, the original version was left to see how much the community would be actually willing to maintain them. My stance has been that I didn't believe the community would change any; but I have been 100% committed to allowing the community to prove me wrong and send in any PR's and I would publish the new version fairly quickly.

Sadly, my prior blogs posts on the problem, which tells the sad tale of how many PR's per plugin is received from the community before ProPlugins was created. The communities involvement still has not changed, and as such we have still only seen less than a handful of PR's for all 40 of the plugins we forked into ProPlugins. Meaning the vast majority of all these plugins probably don't work with NativeScript 6.x. This doesn't surprise me, since I had seen this lack of involvement for the last 4 years of plugin development...

The most interesting thing, is that this experiment really could have gone a couple ways. I could have been proven wrong and the community would have finally stepped up and worked on fixing all the plugins for NS 6 support. Or even the worst possible outcome, nobody could have joined, and also nobody did anything to fix any plugins. However, it seems the community has decided that joining ProPlugins as the best option to move forward. It eliminates them from having any additional time commitments, and helps us create sustainable source code.

So how has has ProPlugins done?

We grew to have 40 fully maintained plugins, which have had around 30 PR's for issues introduced in the NS 6.0 upgrade. We have done several PR's for issues people found in the last couple months to several of the plugins. We have also added several new features to multiple plugins. Finally, recently about 10 PR's for different plugins to fix the breaking change that was accidentally introduced in NS 6.2. So adding and maintenance of existing plugins seems to be off to a very successful start.

In addition, this new year we have several new plugins that we have plans to add. Even better, we have more authors lined up for joining the ProPlugins program. So by the end on 2020; we hope we will have around a hundred fully maintained top quality plugins in the program.

Despite the lack of any recent advertising and really my total lack of my focus on it for the last couple months; ProPlugins has each month done considerably better than the prior month. So our subscription revenue has been increasing faster than I had planned.

Since 80% of all revenue goes to the authors, the remainder goes to the actual expenses like paypal fees, advertising, servers, etc. We believe, the ProPlugins experiment has successfully started the process to having sustainable source code in our community, completely from the community. So a big congrats to the community for helping fund this!

We hope you all have a merry Christmas, and a happy New Year. We look forward to even more of you becoming part of the ProPlugins project and helping us fund sustainable open source for the NativeScript community.

NativeScript Offline Plugins

There are cases where you might want to package plugins with your app in your version control; like for example you are using a commercial plugin or maybe a proplugin and need to use cloud building.

The simplest setup that I have personally used is in the very root of your application.


You create a folder called plugins. Inside this folder you put any commercial and plugins you need to keep with the apps source. For example one of my projects looks like the above picture, I have 5 plugins that are actually in version control with the application. So anyone checking out the source code from git will get all these plugins with the application.

To use these plugins in your NativeScript app, in the root directory you type "tns plugin add ./plugins/nativescript-compress-0.0.1.tgz" you need to type the ENTIRE name including the extension.

How do I download them

So say I want to have the proplugins/nativescript-dialog plugin.

npm pack @proplugins/nativescript-dialog
will download the latest .tgz file into the current directory for you.

PSA: NativeScript 6.20 - Is a Breaking Change release!!!

Upgrading to 6.2.1 and the latest Nativescript-angular (if using angular) and the latest proplugins; should fix MOST issues that 6.2.0 had. However, I still highly recommend the webpack rewrite rules at the bottom of the post to solve ALL the issues.


NativeScript follows the SemVer process; so normally they would have bumped a major version on breaking changed. This break is mostly an un-attended side effects of a couple things. And unfortunately they didn't realize it broke things, so we now have 6.2 which breaks things... Oh well, mistakes happen, life will go on. And so this post is to make you aware of what things you want to change when you upgrade to NS 6.2.0...

To Upgrade or not to Upgrade, that is the question!

I do want to make sure I am VERY clear -- I do NOT think this was a bad change, nor do I think NS 6.2 is a bad release! My apps will be upgraded to it. It offers a lot of good features and fixes. It is just that being aware of the issues will help you make sure you don't have any issues with it when you do upgrade to it.

Lets dig in to the issue.

So lets get some details, first about 3 major versions ago in 2017, my business partner and buddy Nathan Walker proposed on issue 4041 to move the nativescript tns-core-modules into its own namespace. @nativescript along with other nativescript pieces being put into that parent namespace...

So based on this you might guess where the source of the issue lies now.

If you read the above issue; you will notice Peter (another awesome developer) and I both recommended that they do this in the 6.0 release. I personally felt like a hard break would be the safest course of action. Just eliminate tns-core-modules totally. Since they already were totally breaking the build tools, and also breaking other plugins things in v6.0 -- they might as well add this to the pile so we deal with all the breaking changes at one time in plugins. Unfortunately, our advice wasn't taken, or it was missed and so here we are with a very interesting breaking change that I honestly did NOT foresee when I recommended they do it in the initial 6.0.

There are three different issues here that stem from the same cause:

First, if you are using NativeScript-Angular and use any third party plugins -- you might find that they are failing because NativeScript-Angular was moved into the @nativescript/angular namespace. The compatibility imports for the old namespace; is apparently missing a couple redirects so plugins trying to load them fail. I'm sure these plugins will be updated shortly; but right now they are broken. (This has been fixed in the latest version of NativeScript-Angular)

I do NOT know yet if NS-Vue, NS-Svelte, or React-NativeScript have any issues; but odds are a fairly low with them because they are third party and were not moved into the @nativescript namespace, so apps depending on this probably are NOT affected directly (other than by any other plugins.)

Second, because of the design of the tns-core-modules redirect, the redirects waste a little bit of running memory. If your app or plugin imports tns-core-modules/BLAH (which all apps do before 6.2) then webpack will give you Object #1 tns-core-modules-blah, however, when a plugin or the core modules loads @nativescript/core/BLAH you get Object #2 nativescript-core-blah -- they LOOK the same but they are different objects each using memory. This does increase a little bit some parsing and memory that the V8 has to use because you now have basically more than a single framework in memory. Some of this is mitigated based on how objects are tracked; but some of it isn't. So this creates some other un-intended side effects of little bit more GC pressure, more ram usage, and the nasty pitfall we will discuss later...

Finally, if you are using any plugin that does any sort of class monkey patching, they will now all fail -- in this category is things like my very own nativescript-platform-css, nativescript-orientation. The reason why is because of the above allocation issues. Object #1 != Object #2. monkey patch Object #2, doesn't monkey patch Object #1. This is a corner case; as it requires you to actually replace the class (i.e. the top level object). So any plugins that rely on nativescript-global-events which extends and enhances the page class; were affected.

As an aside: The good news is virtually every one of my plugins on https://proplugins.org has been updated to have a NS 6.2 version. If you find a plugin that no longer works after you updated to 6.2; let us know and we will attempt to get it fixed. The 6.1 -> 6.2 fixes are very minor; so they can be rapidly put into the plugins.

One final note -- Please see the method to update the webpack at the bottom to have webpack rewrite tns-core-modules to @nativescript/core this is still highly recommended as some plugins will still be broken if you are still using the tns-core-modules redirect version.


The low level nitty gritty details - Proceed with caution.

For those who are interested in the nitty-gritty; we will walk through why #2 and #3 occur in NS 6.2. Please note this is VERY simplified -- The actual TS -> JS code is a bit more complex and a wrapped object. However, this should give you an idea of the why's...

V8 basically keeps a object map of how a object looks in memory; so if I have file "Blah" with class HiYa -- that looks like this:

export class HiYa {

   function hi() { /* do something */ }

}

When it exports it has a unique signature. In NativeScript this is compiled down to ES5 code. So this will basically look like this when all said and done:

function HiYa() {} 

HiYa.prototype.hi = function() { /* do something */}

module.exports = HiYa;

Now when I do a const HiYaRunnerMaster = require('@nativescript/core/blah'); The Blah.js file is loaded into memory; parsed and then a runnable object representation of this is passed back to HiYaRunner, lets call this HiYaRunnerMaster. So far so good.

Now for the NativeScript tns-core-module redirects / compatibility layer.. This is the exact code that you see in tns-core-modules/* in 6.2... It basically redirects to the @nativescript/core version of the file. Seems simple, and unless you are paying close attention you might not even see why this actually is a problem.

function __export(m) {

    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];

}

Object.defineProperty(exports, "__esModule", { value: true });

__export(require("@nativescript/core/blah"));

So when I do a const HiYaRunnerFromTNS = require('tns-core-modules/blah'); it loads the above code and runs it. . It first defines the __export function, then runs that function on what it gets from the require of @nativescript/core/blah . Seems simple enough. Lets break this down into each step to what the v8/JavaScriptCore engines do.

  1. const tempObject = require('@nativescript/core/blah'); -- THIS object is the same/identical HiYaRunnerMasterObject as we got earlier when we ran it. Every time we do this specific require statement, we get the exact same object. Which is what we want!
  2. __export(tempObject); This runs the export function, passing in our HiYaRunnerMasterObject which so far doesn't seem like an issue.
  3. for (key in HiYaRunnerMasterObject) { we are looping through every property in HiYaRunnerMasterObject
  4. if (!exports.hasOwnProperty(key) verify the exports variable doesn't have this key property already.
  5. exports[key] = HiYaRunnerMasterObject[key]
  6. And behind the scenes exports is passed to the HiYaRunnerFromTNS at the end.

Did anyone else see what happened in step 5? First, exports is a 100% BRAND NEW OBJECT. (our Object #2). We then COPIED all the properties/functions from Object #1 (HiYaRunnerMasterObject) onto this new Object #2 (exports). Each copy is actually a new piece of memory that point to the old object's key value. So the new exports[Key] = old.value. in simplistic terms has two separate memory slots; "Key" and Value". So exports[key] is always a new memory pointer (of key) that either points to the original object's [key]; or to its own copy of a un-boxed object. So the memory usage could be 50% of the original object to the exact same memory usage as the original object, all depending on what the values (boxed or unboxed) are. In NativeScript it should be much closer to adding the 50% additional memory, not the 100% as a worst case number as almost all values on a nativescript key are objects.

At the end, in step 6 we used the brand new object to assign to HiYaRunnerFromTNS. Whoops; so we now have TWO different objects in memory with two different sets of memory usage.

This means that if you monkey patch the HiYaRunnerFromTNS copy; you are not actually monkey patching the actual original and running version. So in several of my plugins, this caused them to break as the monkey patching basically never occurred as far as the running copy of NativeScript was concerned.

In addition their is one more potential gotcha; I'll make a simple example:

let Obj1 = {a: {value: 1}}; // Original Object
let Obj2 = {a: Obj1.a}; // Copied key object

If I do Obj1.a.value = 2; then Obj2.a.value === 2 because both a's point to the exact same memory location with a "value" key in it . However, if I do Obj1.a = {value: 10} then Obj1.a then creates a brand NEW object which also has a value key; of which it has the value of 10 in it. And Obj2.a continues to point to the OLD original object with the value = 1. So even though your objects initially started pointing to the exact same value in memory. A new object assignment will replace just that objects location.

Why does this matter? When since the running instance of NativeScript is the @nativescript/core versions of the object. And your applications code will all currently require tns-core-module versions; you DO initially have two objects but they should all start out pointing to the same memory locations. Just like our example earlier (Obj1.a = Obj2.b) However, if you change a value that is NOT using a setter -- then the value you just changed won't be propagated to the running version, and you will have Obj1.a = {value: 10} and Obj2.a = {Value: 1} and you won't have a clue you just did a noop statement.

I do want to say the above potential gotcha scenario is very UNLIKELY, all code that I can think of runs through a setter; a setter function should be getting and setting the original object's value, and thus they shouldn't go out of sync. But corner cases can and do occur. So my recommendation for anyone updating to NS 6.2 is to do...

Recommendations

  1. Long term, replace ALL tns-core-modules/ with @nativescript/core/ and all nativescript-angular/ with @nativescript/angular/ everywhere in your app. No longer have ANYTHING pointing to tns-core-modules/ or nativescript-angular -- pretend those old namespaces no longer exist and were deleted.
  2. Update to the latest @proplugins if you are using any @proplugins, as most of them have already made the transition, as this will at least save you time on that aspect.

Short term tip (and highly recommended until they have a solid fix):

Richard Smith, posted a good tip that can quickly get you working -- you can add a rule to your `webpack.config.js` file. Find the alias section and add:

   
  "nativescript-angular": "@nativescript/angular",
  "tns-core-modules": "@nativescript/core",

So it looks like:

  
alias: {
      "~": appFullPath,
      "nativescript-angular": "@nativescript/angular",
      "tns-core-modules": "@nativescript/core"
},

NativeScript - State of Plugins - a solution

We currently have a massive number of broken plugins, hiding the few flowers in all the weeds as I discussed in the first State of Plugins post. These  flowers still need nutrients and maintenance efforts to keep them alive as we outlined in the post: costs of a plugin. We went into the long tail of support, and how this burns out authors, and how little (if any) money is actually donated to an author. How have you supported any of the plugins you've used? When authors leave the community;  the flowers they planted, almost always die and are replaced by even more weeds, which of course just propagates the issues… So we are currently at a point where only a few unpaid authors maintain virtually all the plugins.

We also discussed how the two plugin sites deal with all the weeds, and the side effects of both stances, and finally finished off with all the additional issues that are present in the plugin community. Overall, in summary, our community and plugins in general need some help, and we the community has to solve it...

All of these issues, is what pushed me to look for a better solution,  all of this information has been percolating around my brain for a while. Several solutions have been tried by different people (including myself) and unfortunately each has failed over the last couple years.

So lets cover the issues in brief and some solutions that we have brainstormed, discovered, or found other communities implementing as solutions...

Finding the good plugins in all the bad plugins.

There is basically three ways to do this. The first I have actually tried with my PNR (https://plugins.nativescript.rocks) site. I foresaw this issue years ago, which is why I added the ability to put comments and rank plugins. Unfortunately; the community has decided that doing this is too much work (and I don’t disagree – I don’t even do it! ). So very few plugins have actually received a rank or any comments. I also tried to automatically rank plugins, but if anyone has looked at the auto-generated ranks on any of the sites – I’ll be blunt, they are also worthless. So ranking via computer or via the community seems to be a completely failed effort.

The Verified Plugin program - this initially sounds like a awesome idea on its surface. Unfortunately, if you delve into the issues it brings; lets just say that in the grand scheme of things; of what it offers verses what it takes -- this is easily the WORST thing to ever happen to the NativeScript plugin community. have a whole blog post detailing the whys, which will be released at a later point in time...

The final way is to create a curated list of good plugins that are evaluated by people, so that they can be known to be working and/or in a good state. This requires people in the community to spend some time on this and spend more time testing the demos and maintaining this curated list of working plugins and testing it on new releases. Overall this seems like the best solution; but it requires a lot of time and effort by someone(s) .

Working Plugins?

Next issue is now that you found a potential match; does it have a demo? Unfortunately a large number of plugins have bad meta-data and so they don’t even link to their git repo (even the NativeScript team has a few of these). Which means you have to google to try and find the original repo (if it even publicly exists) and then finally download and run the demo. So this step is also a pain, and can be time consuming in some cases, but assuming the author has a repo and a demo, you can try it out. If it doesn't , hopefully it has docs so you can either create the quick demo or integrate it into your app to see if it works.

And the issues keep piling on...

This brings up another issue; now that you have a demo that actually appears to run,  you still have to test all the functionality for the most part upfront to verify it is fairly bug free and it will work for your purposes.

Is the author trustworthy, can I trust their code? (How many of you audit any of the plugins?)

Is the plugin and its dependencies under a good/safe license? I've personally seen several plugins that were Apache / MIT licensed; that use GPL dependencies. This means your actual program needs to be released GPL if you use this plugin.

What happens if the plugin has a bug? Does the author fix it rapidly? Is the plugin even maintained? If you have the time to debug and create a PR, will it even be looked at, let alone merged and then pushed to npm?

Does the plugin author get any donations for a cup of coffee for all their hard work? Wait, that is my issue, and the answer is "nope, almost never". .

Wow, a whole load of interesting issues. Well, now that I have outlined some of the issues, I believe, all or most of them, are solvable with one community driven program.

I want to state upfront, I do know everyone initially is not going to like this proposed solution -- We saw the problem, and we sincerely care about plugins, and the community! We want to see the best for it. As such we are currently using our own time, money, and skills to try and solve this problem in a method, that we believe, the community can and will support. So in total transparency, if you have a better idea – I sincerely welcome you to propose and build it. The more actual solutions to all these issues, means our community has more wins!

Magic?

So what magic is this you speak of? Do we really have a wand we can wave and solve all these issues??? Believe it or not; yes!

I am very proud to announce a plugin authors program to solve all of this.

We call this program ProPlugins.

Sweet, all solved let’s go home… Oh wait, you want the details, don’t ya…

The Details

The idea behind ProPlugins is that it  is a curated list (solves: finding plugins) of highly maintained and top-quality plugins (knowing if a plugin will work), from top authors (trustworthy). Issues are resolved appropriately, PR’s are looked at in a timely fashion. Metadata in the plugins are correct (metadata issues) and link to the proper repos and even a link to download the most current demo. All plugins will be required to have  at the minimum, a NativeScript-Core demo (the demo issue). All plugins have documentation (the doc issue). All plugins are supported by all the authors on the ProPlugins team (the maintenance issue).

Phase ONE requirements are tough enough to move things forward; however, they are not as stringent as phase two and three as we have a whole outline of how to get from here to there and then to have the very best plugins any community can possibly have.

In other words; we as the top authors in the community are replanting our flowers in a new weed free garden, and then as the caring gardeners we are, taking care of all our plugins as the ProPlugins team.

So how does the community fit in? The other part of the solution is how to let the community help solve the issue… In the past the community hasn’t really helped much with maintenance of plugins (*3), it hasn’t helped much with actually handling plugin issues or answering questions on the repos. Nor has the community helped with rating plugins. So basically the community has been mostly absent… So why is this? Each of these items takes time, and most of the community has a job they do, then spend time with their family, and finally most enjoy doing other hobbies. So they don’t have the time to help with all these things, and many times assume someone else will help, in other words there's not much incentive . This is very common in the open source world, the number of stars a project gets verses the so few people that help. NativeScript has over 17,000 stars; but has only so far 100 contributors; and the majority of that 100 are paid Progress employees. So instead of requesting the community donate their time  in areas that it obviously has not been willing to help in for the last 4 years; we will change the narrative…

This is going to be a subscription program. I know what you are thinking, "are we nuts???" Please bare with me; while I explain why we choose this route and why you will actually really want this route...

The community helps by paying a small monthly subscription  to access all these maintained plugins. They don’t have to work on them, they don’t have to help with issues, or do anything they haven’t wanted to do for the last 4 years. So the community can continue as-is, but it is now going to help support itself a different way. This low monthly fee is then used to fund all the maintenance and enhancements on all the plugins in the ProPlugins program. You the community, will be  supporting all the authors of the plugins, making it sustainable open source. Your subscription will help support the maintenance of the actual plugins you use. So now this becomes a totally win-win situation! The plugins you use become higher quality; which then means you spend less time searching, fixing, and testing them. Second because the costs are spread out across the entire community your monthly fee is so small, you won’t even miss it. This co-operative helps everyone (including you) in the community out. A simple low cost on your part can = High Quality for everyone. Honestly how much better can it really be?

So the better question to ask is, what is your time worth? In this case, ProPlugins will save you massive amounts of time, energy, money and frustration. Instead, it gives you what you need on a silver platter worth millions(*1) for  less than the cost of a meal at a cheap fast food restaurant… Can you really afford to pass it up?

Being the plugin developers that have been in the community the longest; we hope  the community will want to go in this direction; since we believe this will fix virtually all of the issues that have plagued us for the last 4 years, and gives us all an incredibly bright future. But, to emphasis how committed we are to the community, let me give you a small example: When I started planning the ProPlugin transition, I personally had planned on moving pretty much all my plugins over to the ProPlugins. However, when I ran all the numbers, I found out that my NativeScript-Permissions plugin is used in a large number of plugins as a dependency. Because we don't want to force the community to do anything, it will continue to be supported on the public npm so that everyone can continue to use it without us breaking anything (and it already fully supports AndroidX!). Our heart really is for the community!

Who is behind the ProPlugins?

Multiple of the top 10 plugin developers have come on board for the initial release. In addition several others have committed to joining in the very near future and are working through the NS 6 issues in their plugins -- but were unable to join the start of phase 1 due to the very short window that we had to work in. We were aiming to release very close to NS 6’s release; and we still ended up launching a bit later than we wanted to.

So what is the cost?

We are starting it out at $9.99 per month for the first 500 subscribers; then it moves to 12.99, and finally at 1000 subscribers it goes to 15.99. We want to reward the first subscribers, that are willing to become a major part of the solution. In addition, as long as you keep your subscription active; your rate will stay the same as a thank you for joining when you did!

So what does this awesome subscription give you:

  • Access to a private gitlab repo where all support, development, issues and feature request will be handled.
  • Open source plugins (yes all the plugins are still open source)
  • Access to a private npm server (You can easily do npm i --save @proplugins/nativescript-somename ---- tns plugin add will be working shortly after the NativeScript team accepts a PR to fix a bug in their code. ).
  • Access to timely bug fixes and/or your ability to ask for features (not guaranteed to be implemented)
  • Access to a curated list of plugins, which we hope to grow over time with plugins that have been abandoned by their original authors. (We have several in mind already, and one already in the list.)
  • Access to easy to use search, quick links from the npm web server to issues and a direct demo downloads.
  • Access to a boat load of plugins from top authors, some of them never released before!
  • Plugins that are already tested and work in NativeScript 6
  • Many new plugins being added daily (we were in time crunch; trying to get close to NS6’s release date. So there are quite a few plugins that didn’t make the initial cut off date; that should show up shortly as we finish testing them all under NS 6)
  • Some Phase 2 plans, based on subscriptions:
    • NS-Angular and NS-Vue demos and instructions for those flavors for all plugins. We would like the plugins to be all inclusive.
    • Integration and demo testing in Preview/Playground
    • Integration with PNR, to search and filter only ProPlugins
    • Screenshots for all plugins
    • All Dependency licensing in plugins license file.

“So where do I go for this awesome deal?" I am glad you asked; You can join the cooperative at 

proplugins.org

In addition you can see all the plugins that already exist in the repo on our npm server at     https://npm.proplugins.org

We hope you are as enthusiastic about where we can take these plugins and the jump in quality that we can do with the entire community participating. We have an awesome road ahead of us, with all of your help.

Sincerely all of us at the ProPlugins Team

*1) According to the Comoco scale we have over a million  dollars in development costs that we have already poured into these plugins over the last 4 years. If you had to recreate every plugin in the ProPlugins Co-op, you would be out a lot of money. If you do have that type of money, we do accept donations and/or sponsors!

*2) If you are a plugin author that would like more information on how this project works, and how we plan to do compensation; please see our website.

*3) Community numbers for involvement in the top 40 plugins is actually rather poor. The numbers show such low participation on those 40, that in most cases it is actually non-existent for the rest of the plugins. This is very typical in all communities, not just NativeScript.

NativeScript - State of the Plugins

Broken Puzzle Pieces

I had a discussion the other day with one of my buddies at nStudio. I was lamenting the fact that our communities plugins really really suck. It doesn’t matter if you use my site PNR (https://Plugins.Nativescript.Rocks) or Progress’s MarketPlace. Trying to find an actual working plugin seems like a trial almost akin to having a tooth pulled.

What is this? Its a video version!

The Video to go with the blog post!

Quantity

Mountain of Plugins

Normally a larger quantity of things is better than a smaller quantity, like I want more money than less. But a smaller quantity is considerably better in many cases, how quickly your app starts up, or how quickly you can build your app. So which is it here? That is a hard one, normally more plugins means more features you can add to your app. But our community seems to have been struck with the "Lets create a useless fork" virus. The larger quantities of Plugins is not our friend at the moment.

Normally having 1167 plugins would be considered a good thing, however, because of how many weeds we have in that 1167 plugins -- this now presents the problem of finding an actual flower in all these weeds. Both sites have search engines, so at least you don’t have to look through all 1167 plugins to find a specific plugin. So lets try a couple examples:

Let's first look at the keyword Dialog.

If we use the Market place we see there are 13 plugins that have the word dialog in them. If we use my site, PNR, we get 8 matches. Whats the difference? Well let's look at each one…

First, the Marketplace has the extra results (found primarily from bad meta-data):

  • Loading Indicator (doesn’t have anything to do with a dialog)
  • Essent Loading Indicator (ditto, and a fork of the above)
  • Loading Indicator SSI (ditto, and another fork)
  • Loading Indicator New (ditto, and another fork).
  • Nstudio NativeScript Dialog (a fork of NS-Dialog)

By default PNR, black lists all forks. This is in an attempt to eliminate what I consider the largest source of weeds. In almost every case I have ran into with forks they are virtually worthless and just add more noise to the results. So, looking at the above list, we have 3 of 5 plugins found on Marketplace were forks that really didn’t add anything. The final fork, is a fork I made on a plugin abandoned by its author. My fork works, so it is actually a good result, that my own site, PNR, didn't show. (*1, *2)

So, on one hand Market place did give you an extra good result; but it also gave you several extra bad results, that you have to manually filter out. This is especially bad with something like notification – PNR has 20 plugins Market shows 31. Any guesses about those extra 11 plugins?

This is an interesting issue and one that both plugins sites have opposing directions on how to deal with. So according to the Marketplace they have 1167 plugins in their database. My database only shows you 1050 of the 1379 (*5) that I currently track, (Numbers are as of July 5th). So based on 1167 vs 1050; the primary difference is because I’ve eliminated that extra 10% of the plugins because they were all forks. I want you to really think about that number, 10% of all plugins in our community are either forks with no changes or forks with minor changes. And that doesn't even count those that are side-forked (*6). So now we have multiple forks that may or may not work; mostly abandoned, and in a lot of cases these are forks from the original plugin, which usually is one of the better plugins in the community and is actually maintained…

Image by _Alicja_ from Pixabay

So we have a lot of weeds in our flower garden. Which can frequently make it hard to find that lone flower in the sea of weeds. Sometimes it will stand out...

Working Status (or Quality)

The second issue, and bigger issue is the actual Working Status/Quality of the actual plugins that you do find. If all 1167 plugins were working, the first issue would not be as big of an problem . Yes, it would be annoying to filter through the sheer volume of forks; but at least we would know they worked..

Lets again take our dialog query example from above… We are pretending that we are using NS 5.4, as in NS 6.0 pretty much all of these broke and now need some fixes...

- The first plugin in the list is done by Shiva (@ nStudio) and updated only a couple weeks ago; NativeScript-CFAlertDialog, I can guess that it will work out of the box. His docs have screen shots, and sample code. All in all looks like a high quality plugin.

- The second plugin in the list is NativeScript-color-dialog, I can also guess this will work out of the box as it was done by Brad (@ nStudio) and was also updated recently. So far two for two are probably in a good state…

- The third plugin is NativeScript-Dialog; it shows the last time it was modified was 2016; odds are, just based on that alone, is it is much more likely to be broken. The weird thing is that the Marketplace says it is NS 5 compatible. Since I maintain the actual working fork of this abandoned  plugin, I can tell you with absolute certainty this version of the plugin does not work in iOS on any version of NS. So 2 out of 3 working is still not bad so far.

- Next plugin is NS-EasyDialog – Its a fork of NS-CFAlertDialog and an older side-fork at that (*3)… 2 out of 4. So we are now at 50% of the plugins are believed to be good…

To speed this up, I won’t document each of the plugins, just the final numbers. So by the time we finish looking at all 8 plugins on PNR; we are at probably 62% of them in good working order. If we use the Marketplace and look at all 13 plugins found: We have probably 53% in good working order . Considerably better averages than I had expected, when I started this blog. I have frequently seen less than 20% working for some plugins. We still had to look at each one of them, and then evaluate if it met our needs, so we're spend time going through 8 (or 13) plugins. Then once we  have a list of those that meet our needs we need to actually download and try the demo, to actually verify it will work (assuming they have a demo). Which is where we would have typically figured out that only half of these actually worked…

In addition we might also need to search for “alert” and “toast”. It really is depending on what you are needing to show on the screen.  Searching with “Alert | Dialog | Toast” (*4) the total number of plugins found is 15 plugins on PNR, and approximately 28 on Marketplace via 3 separate queries. So we  might actually need to look at 28 different plugins to find (hopefully) the one working plugin we need.

Now, just looking at one simple keyword dialog, we quickly estimated the quality of working vs non-working is somewhere around 62%. But the truth is, I didn’t actually download any of these plugins or actually try the demos, I just “assumed” they worked because several indicators were present that made me be able to make a decently good judgment call on if they are still working. As a counterpoint – In one case last week, out of about 20 plugins I actually did a check on, not a single one actually still worked in the current version (5.4) of NativeScript. The reality is that out of 53%/62% actually is still high, once we attempt to download the demos and try them their is a very good likely hood that we will have excluded a couple more.

In addition, like the example above with the NS-Dialog plugin. You don’t actually know if it works on both iOS and Android still. You could download the demo, and the plugin might behave beautifully on one platform and still be totally broken on another… So running the demo on both platforms is pretty much necessary  to verify everything is still working. Hopefully a demo exists and the demo actually tests the functionality you need.

So as the community gets bigger and older, the quality of the plugins is now becoming more and more  hit or miss. Even some of my own plugins I forget to put things in the docs, or when I wrote them originally I didn’t even think a demo was needed. But community wide; this issue is a growing problem. There are many plugins that just have no documentation or literally anything except a name. In addition the metadata provided to NPM which PNR and Marketplace uses to filter and display them is also  broken in a large number of plugins, which then makes searching and finding more hit and miss.

Oh, and if you are using a flavor of NativeScript (like NS-Vue, NS-React, or NS-Angular) the results are considerably worse for you. Frequently the plugins haven’t even been tested in any of the additional flavors. The only way to improve the quality is for someone to actually spend the time fixing the source, readme’s, metadata, demo’s, testing and documenting how to make them work in each of the flavors, etc...

The Top 40 Open Source Plugins

Let's switch gears a bit and look at some additional real numbers. So I took what are the top 40 plugins based on NPM downloads and then ran some numbers and gathered info on all of them. First, I excluded the NS-UI-* plugins by Progress. They aren't actually open source; and their repo numbers totally screw with the averages (in a very bad way). So it makes more sense to exclude them as Progress employees are paid to maintain them and the number of open issues is crazy high...

Most open source authors are unpaid; I even have a recent blog article about this outlining the costs of an actual plugin. Which, if you are unaware or you think that authors get paid for them; that article  will give you some clarity of what is facing an open source developer and how much of their time and money they put into a plugin. If you haven't read it, please stop and do so  now!

Secondly, the top 40 open source plugins get about 28,000 total downloads per week. These 40 plugins are written by only 12 authors. About 1/4 of the 28,000 (~ 7000 downloads a week) are from 9 of the plugins that I wrote.   So, I can give you a pretty good idea about how much support I personally see on my repos for the percentage of usage that those plugins get.

in 4 years, on my 9 Plugins, I have had 6 excellent PRs out of the 44 accepted PRs from the total of 70 PR's that came from the community (The reason 26 weren't accepted is either they were duplicates, they didn't add anything, or changes were already in place, but not pushed to the repo yet). I personally will accept as many PR's as possible, no matter how poor quality they are, because I really want to encourage more. A large percentage of the 44 accepted were actually from several of these same top authors (or people at Progress).   Where in that same 4 years, I did 340 commits for a total of 139 releases, all for free. As you can see the scale is pretty heavily unbalanced to the author doing the majority of the work.

Total PR's for 4 years in my 9 top plugins

 Remember, these 9 plugins are part of the top 40 most used plugins. So how much real community involvement is when their is a whopping total of only 11 PRs a year for all 9 plugins. Yes, you read that right, basically the total of 1.2 PRs, per plugin, per year! Of that 11 PRs per year; 10 of the PR's are small trivial PR's, and 1 is a decent PR.

Total PR's for all 9 top plugins in 4 years

Now if we look community wide at the top 40 plugins in the same 4 years; they have had over 3700 issues; of which 783 are still open. This means that on average these  12 authors that own those 40 plugins, have to deal with 77 issues a year each. Frequently these issues will require testing to see if the author can duplicate the issue. If they can, then finding the issue and fixing it... It actually is a testament to how much these authors care about the community , that they still have close to an 80% closure rate.

This is not sustainable; almost 4000 issues in just the top 40 plugins, all handled by basically 12 people whom I would venture most (if not all) of them are not paid to do any of it. Now to put this in even more outrageous numbers; I myself actually have 25 open source plugins! Not just those top 9; that we have been discussing above. So the additional 16 plugins, which are not used as much, still also have issues, and fixes that have had to be done. The other 11 authors; also have additional plugins. In fact the top 5 authors in the community have almost 200 open source plugins that they wrote and support.  If we get that poor of community support for even the top 40 plugins, how much support do you expect is expended on the rest of even less used plugins in the community?

To say the least; these numbers are very depressing at how few people are actually holding up the plugins in the community...

Breaking Changes

Now depending on how long you have been in the community; you may not realize that basically each major release of NativeScript has broken a part of the plugins. This means that NS 2 -> NS 3 required fixes (some not so trivial). NS 3 -> NS 4, NS 4 -> NS 5, and now NS 5 -> NS 6. Each of these releases had breaking changes; unfortunately this time is no different and there are a couple different breaking changes in the new NS 6 update. This is one of the major reasons the plugins in the community are in such disarray. Many plugin authors have come and gone over the years. Those plugins may have been top notch when they were released; but no one picked them up when that author left. So you still find many plugins from NS 1, 2 and 3, that sound awesome, but don't work because the original author left and no one from the community stepped in to maintain it. I have 25 plugins that I need to verify work in NS 6, trace down any issues and commit fixes to them, all for free. That is a lot of time and energy...

Community Involvement

I have discussed with Progress about money for the plugins issue; and they have told me in no uncertain terms that there is no money for plugins. The answer did not surprise me, as based on why NativeScript exists this is not an area that they believe will help its core purposes. So it is not an area they are willing to fund. I didn't want to assume it, and there was no harm done in asking.

So this obviously then becomes 100% the communities problem. We now have over a 1,000 plugins in the community and another large chunk of them broke with the  new NS 6 upgrade. Unfortunately most will probably permanently join all the other plugins, in the plugin graveyard, that died in the prior NS 2, 3, 4 and 5 updates.

Possible Solutions

  1. Money from Progress (Nope)
  2. Money from another large sponsor (Who??? )
  3. Verified Plugins Program ( Creates even more issues, -- uh, Nope. )
  4. Community stepping up, by doing a lot more work to fix existing plugins via PRs ( That would be awesome, but seems unlikely. )
  5. ???? Please make some suggestions ????

*1 – PNR has been updated since I wrote this blog article to hide the original ns-dialog, and re-enable showing the working fork nstudio-ns-dialog. But initially it was opposite, and I’m willing to be totally fair and say my site had some bad results.

*2 – If you have created a fork of another project that you are maintaining because of major feature changes and/or the original author abandoned it – please let me know; I’ll white list it on PNR.

*3 – I have already black listed this fork now on PNR, as it is a unmaintained fork (which was not tagged as a fork because it was side-forked...

*4 - PNR actually support | and & in the main plugins search filter; However, it can ONLY use one at a time. The first one it finds, it uses for the rest of the search So if you doblah | blah2 &amp; blah3 it will treat it as blah | blah2 | blah3 -- sorry I was very lazy when I quickly wrote the parser, and it is undocumented "Feature". In future versions, I will probably beef this up to allow things like (x | b) &amp; (c | d) but at this point, it is really simple stupid and unsupported.

*5 - the extra almost 300 plugins that I track are plugins that were depreciated, or aren't actually NativeScript plugins. The original developer used a set of key words that made it show up in the tracking set that I track from NPMJS, so they had to be tagged as invalid to eliminate them from view.

*6 - Side forks, are where the person git clones the repo; but then creates a new repo with the code and it isn't "linked" to the original repo. i.e. it is a fork, but was forked "outside" of the a normal fork method. Unfortunately, I have not figured a good way to detect this, because it no longer has a link back to the original repo as a normal fork does.