Monthly Archives: July 2016

NativeScript: WebPacking

The NativeScript team released a cool plugin using the "WebPack" code to packup the entire code base and since it does things like tree shaking; your end result is a much smaller app.

Well I had an opportunity to test it over the last couple weeks for a friend of mine (Nathan Walker) as he is prepping to release a very very cool app.

However, the NS-Webpack plugin is unfortunately very (very) buggy; and odds are very (very) likely if you are doing anything beyond a very simple application; it will not work.   You can see a stack of bug reports in the repo for all of these issues I mentioned and some others; so hopefully these issues will soon be just a distant memory, and it will work as intended.

So many days later; and after much debugging, we can declare that we have smacked and cajoled webpack into shape and we were able to get it to actually webpack an application properly!

So here is the things you need to do if you want to webpack something while it is in its current state...

Fonts

The first thing you need to be aware of; is that on iOS if you are using any custom fonts; the automatic font registration is totally broken when webpack'ed.  The solution is to fallback to what we used to have to do on iOS; which is manually register the font.   The code I wrote for this project looks like this:

if (global.NSObject && global.NSString) {
  var font = require('ui/styling/font');
  font.ios.registerFont('fontawesome-webfont.ttf');
}

Basically the if statement tests for iOS, then I manually require the font class; and finally the last line; I registered the font I needed.  You can repeat the last line for each font you are using.

Pathing Issues

The second issue is only if you use your screens/components in a subfolder type system the url pathing to find them breaks under webpack code.  So when you have something like this:

/app/components/blah/
-blah.js
-blah.html
-blah.css

and inside your blah.js you have code like this:
Blah = _decorate([
...
templateUrl: 'blah.html'
...

This will fail; ALL the JS is actually bundled into the webpack'd bundle file; so when it goes to try to find this file, the JS code is running from the root directory of your app.  Where your actual html file is not in the root.  So you have to change the path to be:
templateUrl: './components/blah/blah.html'

Pretty simple fix if you know about it; but man if you don't it starts crashing...

Crashing on Startup

The final issue is simple and complex at the same time.  NativeScript iOS runtime has some built in short-circuits for __extends and ALL the Native objects (i.e. like NSObject, NSString...) -- well Webpacking unfortunately changes the signature of the __extends function and so the runtime doesn't detect that the function is actually a __extends...  This causes the runtime to run code that isn't actually supported and so it, well, crashes...   This can be solved in one of two ways;

  1. You edit each of the plugins that are installed and manually strip out the __extends function.  (and then let the plugin author's know to disable creating the __extends in their plugin as this code normally is just pointless and a waste of space and memory, and in the webpack case it is now deadly -- So just add "NoEmitHelpers: true" to the tsconfig file).
  2. You add a simple plugin that I wrote to your main project directory; this plugin will automatically strip out all __extends while it is webpacks so that it doesn't matter if the plugin author forgot to set that flag; the simple plugin eliminate it.

/**********************************************************************************
 * (c) 2016, Master Technology
 * Licensed under the MIT license or contact me for a Support or Commercial License
 *
 * I do contract work in most languages, so let me solve your problems!
 *
 * Any questions please feel free to email me
 * Version 1.0.2                                      Nathan@master-technology.com
 *********************************************************************************/
"use strict";

function eliminateExtends(pre) {
    var i = pre.indexOf('var __extends = ');
    if (i === -1) {
      return pre;
    }
    var x = pre.indexOf('};',i);
    return pre.substring(0,i) + pre.substring(x+2);
}
module.exports = eliminateExtends;

You copy this code into an eliminateextends.js file in your root folder of the project; and modify your apps webpack's config file to use this as a loader plugin.

Please note this is not all the bugs in webpack; there are a couple others on the https://github.com/NativeScript/NativeScript-Dev-WebPack/issues repo that we didn't run into; but these were the only ones that we ran into for a iOS NG2 project.   So make sure you check out the bug list if you are still having issues...

Happy NativeScript-WebPacking!