AOT and rollup

JIT compiling angular2 works and runs fine with importing the namespace like this:

import * as go from 'gojs';

and loading the go-debug.js file via the system.js module loader. I have no issues typescript compiling the app, the issue is with AOT compiling the angular app and the subsequent rollup. When you move an angular2 app into production you want to AOT (Ahead Of Time) compile it. The difference is waiting to load 100’s (possibly 1000s in larger Angular2 apps) before angular bootstraps, or 1. In order to get all your typescript files into js files and then mushed into 1 js file, angular recommends using some plugins.

The plugin that is failing to execute is called rollup-plugin-uglify. So once all rollup preforms a treeshake, and removes all un-referenced modules, it tries to execute the rollup-plugin-uglify.uglify plugin that basically minimizes the generated js (remove whitespace and make all js variables singe letter, etc), so it makes your single js file tiny. That step is failing when i started to refernce the gojs namespace.

I can probably look at using over tools to minimize the outputted AOT generated js file, but If other devs follow the angular2 quickstart and try to AOT their apps per Angular2’s recommendations they will probably get this error as well.

To get past this in the short term i commented out the call to uglify() function in my rollup-config.js file.

import  rollup   from 'rollup';
import  nodeResolve  from 'rollup-plugin-node-resolve';
import  commonjs     from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';

export default {
    entry: 'app/main-aot.js',
    dest: 'app/dist/build.js',      // output a single application bundle
    sourceMap: true,
    sourceMapFile: 'app/dist/build.js.map',
    treeshake: true,
    format: 'iife',
    plugins: [
        nodeResolve({jsnext: true, module: true}),
        commonjs({
            include: [
                'node_modules/rxjs/**',
                'node_modules/gojs/**'
            ]
        })
       //, uglify()
        
    ]
}

But this means that my outputted AOT compiled file is ~2700Kb vs ~270Kb it was before gojs and after uglfification.

Actually it appears that the generated build.js file after the AOT compile, throws a runtime error. If anyone knows how to Angular2 AOT compile an app that imports GoJs, please let us know because this would be a show stopper for us from purchasing this tool.

Thanks,
Chris

I don’t understand what you are including when you say:

    include: [ 'node_modules/gojs/**' ]

Does that mean you are including all of the GoJS files, including documentation and samples? Going from 270KB to 2700KB when including the “go.js” library doesn’t make sense to me.

Yeah i removed that include statement from the rollup-config.js file and I get the same behavior.

To my statement about size I meant that prior to me adding the gojs npm package and importing, I was able to AOT compile and rollup my app producing a singe build.js file that was ~270KB. After referencing gojs the rollup fails and minification doesn’t run on the build.js so the file is bloated to 2700Kb. But worse then not being able to minify it, the generated AOT compiled build.js isn’t executable.

I understand that you guys can’t support all the variations of MVC-ish javascript libraries that are out there, as that is an ever moving target. It’s just in our case we need to be able to precompile our Angular2 application before production depoyment.

I know that there are a lot of Angular2 projects out there that are using GoJS, but I have no idea how many are compiling AOT in the way you are trying.

If you don’t uglify, does everything work?

I would imagine that all of them would AOT compile before going to production, to avoid having users dl 100-1000 .js files to bootstrap angular2.

No, if I avoid the uglify and try to run the app it throws this error at run time:

Here is the line in question
ye.fillPath=function(a){"string"!==typeof a&&v.yd(a,"string",ye,"fillPath:str");a=a.split(/[Xx]/);for(var b=a.length,c="",d=0;d<b;d++)var e=a[d],c=null!==e.match(/[Ff]/)?0===d?c+e:c+("X"+(" "===e[0]?"":" ")+e):c+((0===d?"":"X ")+"F"+(" "===e[0]?"":" ")+e)return c};var Oe;

I would think some users have run into this before if they AOT angular2 while referencing GoJs using SystemJS module loader, unless everyone has just been referencing GoJs through the script tag and doing a

declare var gojs:any; in their typescript…

Unfortunately we haven’t run into this problem before. Is there some way you can still Package go.js with your bundler, but stop it from being minified/uglified any more than it already is?

Yes, it seems like the mistake of some minifier or uglify-er along the way. Note that in our code I see:

((0===d?"":"X ")+"F"+(" "===e[0]?"":" ")+e);return c}

There’s a semicolon before the return.

I have no idea why this may be happening with your stack, but if you don’t mind trying, what happens if you simply minify/uglify go.js, does the same error present itself?

When I modify my rollup-config.js configuration in order to only rollup gojs, I get this error:

Error: (uglify plugin) Error transforming bundle with 'uglify' plugin: Unexpected token: keyword (return)

Here is my rollup-config.js file:

import  rollup   from 'rollup';
import  nodeResolve  from 'rollup-plugin-node-resolve';
import  commonjs     from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';

export default {
    entry:'node_modules/gojs/release/go.js',
    //entry: 'app/main-aot.js',
    dest: 'app/dist/build.js',      // output a single application bundle
    sourceMap: true,
    sourceMapFile: 'app/dist/build.js.map',
    treeshake: true,
    format: 'iife',
    onwarn: function(warning) {
        // Skip certain warnings
        // should intercept ... but doesn't in some rollup versions
        if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }
        // intercepts in some rollup versions
        if ( warning.indexOf("The 'this' keyword is equivalent to 'undefined'") > -1 ) { return; }
        // console.warn everything else
        console.warn( warning.message );
    },
    plugins: [
        nodeResolve({jsnext: true, module: true}),
        commonjs({
            include: [
                'node_modules/rxjs/**'
            ]
        })
       , uglify()
        
    ]
}

Do you have a reference Angular2 app that loads the gojs module, and successfully AOT compiles?

Thanks!

Not at this time – we’ve just begun learning Angular 2.

If uglify has a problem dealing with the go.js library, can’t you exclude it from being uglified?

mmm, I’m not sure there is a way to do that. When you AOT compile, it does several things, it preforms tree shaking, which weeds out the imported modules that are never used, bundles all the modules into a single .js file, and minifies that resultant js file. Then when you bootstrap angular you load that single file on the page in a script tag:

<script type="text/javascript" src="app/dist/build.js"></script>

And the main.ts file is this:

import {enableProdMode} from '@angular/core';
import { platformBrowser }    from '@angular/platform-browser';
import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory';


enableProdMode();
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory)
    .then(success => console.log('Angular2 Compiled AOT'))
    .catch(error => console.log(error));

Where AppModuleNgFactory is a class that Angular2’s compilation process builds from my app.module.ts file during AOT compilation. I can and have, removed the gojs module import from my component and declared the gojs variable like this:

//import * as go from 'gojs';

//reference to goJs library
declare var go: any;

And I can still use the library with Angular2 AOT, however I don’t get compile time checking against the gojs type definitions, and now the Angular2 AOT process doesn’t try to bundle the gojs module, so AOT compilation works. This is fine as a work around, but as you guys dig into Angular2 I’d be very interested in what you find out around AOT.

So you are saying that when you include:

import * as go from "gojs";

the build process includes the go.js library and everything is uglified together. OK. Of course the real problem seems to be that there is a bug in Uglify. Or am I misinterpreting the cause of the error?

For now, you can try using the old style TypeScript declaration:

/// <reference path="go.d.ts" />

That should avoid the need for:

declare var go: any;

Yeah, I’m not entirely sure where the error is, that is if it’s a gojs issue, or rollup-uglifiy issue. I only know that if you try to import the gojs namespace as

import * as go from "gojs";

in my Angular2 component, rollup and uglify try to bundle up the gojs library into my angular2 app code and it complains about that return statement.

I’m not sure if this is because the d.ts file only exports a namespace and not an es5/es6 module. I have a suspicion that is the case.

Either way, I think it you guys might want to try a helloworld angular2 app that AOT compiles while importing your namespace, because as the crazy president would say: “Angular2 is gonna be Yuge”.

Does this work for you?