Injecting Custom Files into Ionic Build

This post is about including custom .html, .css and .js files in an Ionic 3.x+ project so that they get copied from /src to /www during the build process. Basically, we are talking about files that are handled separately from the webpack compiler process, but you want them to be swept into the test or production build when they get updated.

Step 1: Modify your projects main package.json file in the root directory to override the copying process in ionic:build and ionic:serve. In this example we are referencing a custom library called ionic-config-override.js that controls what we want to copy, and this library lives in the root directory, as well.

{
     . . .
     “scripts”: {
          . . .
          "ionic:build": "ionic-app-scripts build --copy ionic-config-override.js",
          “ionic:serve”: "ionic-app-scripts serve --copy ionic-config-override.js"
     }
     . . .
}

Step 2: Create a JavaScript file of the same name you referenced in package.json for example ionic-config-override.js. In this new JavaScript library use the node.js fs-extra file utility to copy the files you want when the build process is run. Here’s one example:

var fs = require(‘fs-extra’);
fs.copy(‘src/special.html’,’www/special.html’);

Step 3: To test locally instead of using ionic serve, run this new script using the command line command npm run ionic:serve. Or, if you are ready to test on a device run the script using npm run ionic:build android and then when that is completed successfully use ionic cordova run android.

References:
Ionic –copy command

The Copy command source code can be found in your project path @ionic/app-scripts/config/copy.config.js

Additional information can be found on the Ionic forums.

Web Worker Performance Tips 101

There are many potential benefits to using web workers. They can provide a significant web application performance boost by moving heavy-duty work off the main browser thread. It’s also true that in certain instances you may be slowing down your application in ways you didn’t expect.

Tip #1 – The cost of using a web worker is not free. JavaScript must serialize your data to pass it to a background thread and it must also serialize data when sending it from a background thread back to the main thread. That’s two serialization processes for each round trip and each process takes CPU cycles and time. Depending on what type of data and how large it is you may be surprised how long it can take.

Tip #2 – Not all browsers treat web workers equally. Web worker performance gains in one browser may not represent a similar gain in a different browser. If you are building a cross-browser application, make sure you specifically test and measure each of your web workers in the various browsers that you will be supporting. This often takes developers by surprise. The issue is mainly due to differences in how each browser vendor implements their data serialization algorithms. If you want more information on this, its officially referred to as structural cloning algorithms.

Tip #3 – Measure the total time it takes to use a web worker. Set console.time() before the initializing the worker and set console.timeEnd() where you get a message back. You’ll want to compare these results against running the same code directly on the main thread.

Example:

    console.time("parseTestTimer"); // Start the timer
    
    // Initialize the worker
    var worker = new Worker("ParserWorker.js");

    // Send the data to the worker
    worker.postMessage([first.value,second.value]);

    // Get the data back from the worker
    worker.onmessage = function(result){
        console.timeEnd("parseTestTimer"); // End the timer
        // Do something
    }

Tip #4 – Even using binary transferable objects can have a cost. The Transferable pattern for web workers are designed for high performance, however depending on what you are transferring, the browser, the browser version and the device type (mobile vs desktop) your mileage may vary. In more technical terms this pattern, at least in theory, uses a zero-copy, pass-by-reference approach which is intended to have very low overhead. You should definitely consider testing the transferable objects pattern and compare timing benchmarks against the standard web worker postMessage() pattern. You might as well be thorough, especially since there’s no guarantees of how each browser vendor implemented this functionality under the hood.

Example:

    // Transferrable object pattern using binary data
    worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);

Additional References:

Advanced Web Worker Performance – this post provides several important details for determine if your web worker is provide a positive or negative performance gain.

Samples apps demoing no workers, one worker and two workers

MDN – Structured Clone Algorithms

HTML Living Standard – Transferable Objects

Do I need Ionic’s Geolocation Plugin?

Most likely not. As described in the Cordova documentation and Ionic documentation, the plugin is for devices that don’t already provide an implementation. The vast majority of modern smartphones natively support the WebView Geolocation API. Also, cellphone enabled tablets typically have a GPS. However, WiFi only tablets may be limited to using non-GPS, WiFi-based geolocation, but the Geolocation API will still work although it will be less accurate.

Skipping the plugin simplifies installation and implementation. You don’t have to install it and that eliminates any possible conflicts and provides a minor reduction in application size. You also don’t have to import the plugin into your application components and that simplifies your code. You can simply use navigator.geolocation like you would in any regular JavaScript app:


watchId = navigator.geolocation.watchPosition(success[, error[, options]])

Sample application: https://github.com/andygup/ionic2-esri-map

Using High Accuracy GPS with Mobile Apps

There are times when the built-in GPS simply isn’t good enough for your Android or iOS app. Built-in GPS is good for finding a general location of a geographic feature such as a pond, field, or parking lot. If you need to locate a specific parking space, or a geographic feature within a field, or an inlet to a pond then you’ll need much greater precision of a commercial GPS unit.

Examples. Here is a more specific example to illustrate the concept. Let’s say the application users are mapping insect infected trees in a densely forested urban park. If you are using a smartphone GPS, with an average accuracy of 30+ meters when standing under the tree cover, the latitude/longitude coordinates may end up being unusable for future follow-up because there are dozens of trees within a 30+ meter radius. If you are using a commercial GPS with sub-meter accuracy you can have a much higher degree of certainty that someone will be able to locate that exact tree again.

I’ve seen entire days’ worth of data collection get thrown out the window because of significant location inaccuracies caused by using smartphones and dedicated hand-held consumer GPS units that are well known to outdoor recreational folks. I’ve accidentally sent a backcountry trail maintenance crew to a totally wrong location (they got really mad). All I had was a smartphone GPS and my location coordinate was over a thousand meters off even though the Android Location API returned an “accuracy” value of less than 50 meters. Oops — that’s the difference between precision and accuracy.

Good news. The good excellent news is there are small, handheld commercial GPS units that you can tether to your smartphone via Bluetooth such as the Trimble R1. Units like the R1 are able to override the onboard GPS and when configured correctly work just fine with the browser’s JavaScript-based Geolocation API or native iOS/Android geolocation.

The only downside can be cost. Some of these commercial units cost several thousand dollars and that may be outside the budget of many organizations.

Surprise, Surprise. I spend a ton of time talking to customers about this topic. Many people are very surprised because they regularly use GPS fitness tracker apps or Google Maps and the location information almost always seems very close to reality. The hidden trick is these apps use proprietary software algorithms that attempt to slightly improve accuracy, minimize location fluctuations or even intelligently snap your location to geographic features such as roadways, buildings or trails.

When you are building a custom mobile application, you will be forced to deal with raw, unfiltered geolocation data. And the coordinate data is coming from consumer-grade GPS units mass produced at the lowest possible cost. The antennas are tiny and usually on the back of the device rather than pointed towards the sky. The chipsets are designed to minimize battery usage, because GPS can be extremely battery intensive and generates a lot of heat. They have minimal ability to resolve communication difficulties between your device and GPS satellites, and GPS signals are already relatively weak.

Decisions, decisions. If your budget can’t handle several thousand dollars for a commercial GPS and you only have short term needs you can always look into renting a bluetooth unit. Just make sure to ask if it overrides the onboard GPS chip. You can find GPS rental companies online. There are also consumer-grade Bluetooth GPS units that only cost several hundred dollars. The consumer Bluetooth units aren’t nearly as accurate as commercial units; however, they offer a significant improvement over built-in GPS.

Advanced Web Worker Performance

This post offers some advanced considerations on the mechanics of squeezing the best performance possible out of workers. I only mention a few (very) rough benchmarks since the goal is to focus on guidelines and food-for-thought, rather than specifics. It’s also fair to say that not all tasks benefit from using web workers. The best way to know is to test performance with and without the workers.

Processing costs. There are a variety of costs associated with manipulating data. Manipulating data means any task you run against it such as looping, converting, parsing and analyzing. Each one of these tasks should be evaluated for the cost in terms of CPU usage and time spent. By looking at these aspects, you can determine the benefits of having a web worker versus not having a web worker.

Pre-processing – manipulating data before sending it to the web worker.
Peri-processing – manipulating data while doing work on the background thread.
Post-processing – manipulating data after it’s been received back from the web worker.
Total processing – this benchmarks the processing from the very beginning until the very end.

Time stamp before and after each process that handles data. Tools such as console.time are invaluable in identifying actual and potential bottlenecks. Also make liberal use of the developer tools such as Chrome’s CPU profiler that now includes screen captures.

Total CPU and memory usage. There’s often a misperception that just because CPU usage has been outsourced to the background thread that it won’t negatively impact an application or contribute to jank. This is not true, especially on mobile devices that are already CPU and memory constrained. CPU headroom, or the amount available for application processing, is finite and typically doesn’t care whether CPU is used on the main thread or a background thread.

Web apps are wholly dependent on how each browser vendor uses CPUs and manages threads behind the scenes for every browser version and operating system. Using JavaScript you cannot guarantee how the browser will spread CPU load across cores.

In fact, I’ve seen web worker performance improvements made in Chrome that create almost an exact opposite performance decrease in Safari! Talk about a WTF moment.

Cloning costs. Careful consideration should be placed on the costs associated with the act of sending and receiving messages. Sending and receiving isn’t “free”, in fact the amount of CPU consumed can directly cause jank.

Web workers use a cloning algorithm for serializing objects that go in and back out, and cloning uses CPU cycles. Yes, even if you are using transferable objects there may still be performance implications especially when dealing with large amounts of data (>100MBs) as well as on mobile devices. You simply will never know unless you test, test, test.

In some cases, the cloning costs related to both sending and receiving messages may outweigh the performance benefit of using a web worker. If the entire round-trip time and CPU utilization is greater than simply keeping the processing on the main thread – then you probably don’t need a web worker.

Pooled workers. Should you use one worker or several? The only reliable way to know is to experiment. One approach to eke out greater performance is to create a pool of workers. The concept is a task that can be broken up and passed on into smaller concurrent worker tasks and then reassembled after all tasks have completed.

Here’s an example application that retrieves a GeoJSON file, parses it, then displays the data on a map. Open up the developer console and run each application multiple times. You can also download and experiment when this application yourself with increasing and decreasing the size of the thread pool:

Example 1: Parsing using no web workers
Example 2: Parsing using one web workers
Example 3: Parsing using two web workers

With respect to binary versus non-binary data, I’ve seen diminishing returns when using larger number of workers with JSON files. On the other hand, there are a number of posts on the web that show great performance processing image data with increasing numbers of workers.

This also may be dependent on the browsers-threading model and how it uses the number of cores on your device or laptop. How do you know? Test and benchmark.

Re-use workers, or re-create for each loop? There are costs associated with initializing workers. Depending on the type of application, it may benefit you to re-use workers rather than re-create them for each loop. This depends on how complex your web workers are, how many you need to spin up, the type of device they are running on and how often you are using them.

Some applications may run on a timer once every 5 minutes. If that’s the case does it make sense to keep workers sitting unused in memory for that long? Maybe or maybe not. Other applications may only need the workers at startup and there’s definitely no need to keep them around after that. The list of use cases are endless.

Here’s some very rough test results on the time to simply initialize web workers. This example used identical workers that contained 67 lines of code:

Macbook Pro: 2 workers, 0.4 milliseconds on average
Macbook Pro: 4 workers, 0.6 milliseconds on average
Nexus 5: 2 workers, 6 milliseconds on average
Nexus 5: 4 workers, 15 milliseconds on average (border-line UI jank)

As far as computational horsepower, the Macbook used in the tests had 2.6 GHz i7 with 16GB of 1600 MHz DDR3. The Nexus 5 had a Snapdragon 2.26 GHz with 2GB of 800 MHz RAM. Clearly the Macbook outclasses the Nexus. It’s important to note how much longer it took to spin up a pool of workers on a mobile device. That’s an example of an app that would work seamlessly on a powerful laptop, but could produce jank on a mobile device.

Closing Notes. Web workers are fairly straight forward to bolt into an application, but tuning them up to gain the true performance benefits can be a bit more tricky. With a little exploration and experimentation, workers can potentially provide huge benefits for your application’s performance.

Sample Application

[Fixed broken links: July 7, 2016]

Application Cache is not gone, oh my! Or, is it?

Reports of Application Cache’s early demise are false. Application Cache (a.k.a Cache Manifest and AppCache) isn’t perfect, it can be very frustrating to get working and many people hate it with passion, but the fact is that the API will be around for the foreseeable future. I’ve been getting many questions, so this blog post is an attempt to shed some light on a confusing topic.

Mozilla says Application Cache is deprecated and unstable, WTF?

First, let’s review what Mozilla is saying about Application Cache since the majority of questions I get come from what they are saying. Mozilla has some fairly strong wording on their developer site, you can read all about it here. Or, if you don’t feel like following a link, here’s the official text from Mozilla Developer Network (MDN) website. I added the underlines to emphasize wording that’s tripping people up:

Deprecated. This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped. Do not use it in old or new projects. Pages or Web apps using it may break at any time.

Using the application caching feature described here is at this point highly discouraged; it’s in the process of being removed from the Web platform. Use Service Workers instead. In fact, as of Firefox 44, when AppCache is used to provide offline support for a page a warning message is now displayed in the console advising developers to use Service workers instead (bug 1204581).

Mozilla also references the Web Hypertext Application Technology Working Group’s (WHATWG) position on Application Cache. But, their wording is similar but definitely different in meaning from the WHATWG statement in their HTML Living Standard, Section 7.7. You may want to read this several times:

This feature is in the process of being removed from the Web platform. (This is a long process that takes many years.) Using any of the offline Web application features at this time is highly discouraged. Use service workers instead.

An oversimplified description of the WHATWG is it’s an organization that provides research and makes recommendations to the W3C – World Wide Web Consortium. It’s the W3C that finalizes recommendations and makes them into standards.

Also note: Application Cache is, for the moment, still officially part of the latest draft of the WHATWG HTML Living Standard document as shown here in Section 7.2.2 (it’s a big document, it’s best to just search for application cache).

 

What is the true state of Service Workers?

Reality is always nuanced when it comes to cross-browser web application development. Here’s a summary of facts for cross-browser developers to consider (as of February 1, 2016):

  • Service Workers are NOT supported on the following platforms, and you’ll need to use Application Cache if it suits your requirements and any Application Cache bugs don’t adversely affect your apps. You can verify these on caniuse.com.
    • Android Browsers at v4.4.4 and older (there are still a lot of phones out there using older browsers). Yes, a percentage of these users download Chrome. However, as of Feb 1, 2016, Android is reporting that v4.1.x thru v4.4 represents 60.8% of all phones in circulation.
    • Desktop Safari
    • iOS Safari
    • IE and Edge – don’t forget that a lot of offline field worker apps are built specifically for laptops.
  • The Service Worker specification is still a Working Draft according to the W3C. It’s not final according to the official standards bodies. Mozilla even lists Service Workers as “Experimental Technology”. You can view that yourself here. Here’s MDNs wording copied directly from their webpage:

This is an experimental technology 

Because this technology’s specification has not stabilized, check the compatibility table for the proper prefixes to use in various browsers. Also note that the syntax and behavior of an experimental technology is subject to change in future versions of browsers as the spec changes.

  • Service workers are more complex and require coding skills in comparison to Application Cache which requires only a configuration file and one line of HTML code. Here’s an example. It’s going to be a big step for long time Application Cache developers to wrap their heads around using Service Workers. It’s a very powerful API but it’s not going to be as easy as simply swapping out your Application Cache for offline capabilities built on Service Workers.

What to do, what to do?

My thoughts are MDNs statement leaves developers between a rock and a hard place, and holds the most water if the ONLY web browsers you need to support are browsers that have implemented all aspects of Service Workers that meet your requirements. You’ll also need to keep in mind that Service Workers are in beta so they can also can break or not work as expected, and there is a remote possibility the functionality could change.

When you combine MDN’s statement with the WHATWG statement and the WHATWG Living Standard document the picture becomes more clear. Here’s my interpretation: Application Cache is going to be around for a while longer. However, it would be a really good idea for you, as a cross-browser developer, to keep your eye on the progress of Service Workers and to consider using them in applications if/when it makes sense based on requirements and browser capabilities.

Don’t throw away an working/stable code built on Application Cache just yet.   If you are building apps on platforms that don’t support Service Workers then Application Cache may be your only viable alternative until you can upgrade to newer platforms or other browsers.

Additional References: