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