Search code examples
angulartypescriptsystemjsrollupsystemjs-builder

Bundle Angular2 AoT with systemjs-builder and rollup tree shaking


I've spent a good amount of time getting my Angular 2 project to work with SystemJS, and now with AoT compilation as described here: https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

I'm running plugin-typescript with SystemJS to transpile typescript in browser during development. I've got systemjs builder using plugin-typescript to generate sfx bundle out of the AoT (ngc) output.

What I can't figure out is how to get systemjs-builder to tree-shake the angular AoT code. From what I can tell, it seems like systemjs-builder should support rollup (e.g. https://github.com/systemjs/builder/issues/709) but I don't think rollup is running for me when I set rollup:true in my buildStatic options.

My typescriptOptions from systemjs.config.js

transpiler: 'ts',
typescriptOptions: {
  target: 'es5',
  module: 'es6',
  emitDecoratorMetadata: true,
  experimentalDecorators: true
}

my buildStatic call:

 builder.buildStatic('app/main-aot.ts', paths.wwwroot + 'dst/build-aot.sfx.min.js', {
            minify: true,
            rollup: true
        }).then(function (output) {
            console.log(output.inlineMap);
        }, function (err) {
            console.log(err);
        }),

I got the piece about output.inlineMap from this github ticket: https://github.com/systemjs/builder/issues/639

But it isn't clear to me what I should expect. Right now it simply outputs {}

This is all really new to me, I might be completely misunderstanding something. Looking for anyone to help me identify whether or not rollup is running, confirm that it should be possible, and hopefully get this sorted out if it is.


Solution

  • I was able to discern that when rollup properly executes, the inlineMap property on the builder result will be a name value collection of arrays:

    { "key1": [], "key2": [] ... }
    

    Each key reflects the name of an input file into buildStatic. I don't use any glob patterns, i run buildStatic by feeding it the single entry-point (main) file for my angular app, so I get one key in the map.

    builder.buildStatic("main.ts", "out.sfx.min.js").then((output) => {
       console.log(output.inlineMap); // => { "main.ts": [...] }
    });
    

    The number of items in the array mapped to the key I've interpreted as the number of optimizations made during the rollup process... I'm not sure if this is technically 100% accurate, but I use it in my build output as confidence that the rollup process actually did something - where bigger numbers are better.

    For posterity - I use the following gulp function to buildStatic and pretty-print results...

    const builder = require("systemjs-builder");
    const filesize = require("gulp-check-filesize");
    
    let opts = { runtime: false, minify: true, mangle: true, rollup: true }
    let inFile = "main.ts";
    let outFile = "main.sfx.min.js";
    builder.buildStatic(infile, outFile, opts).then((output) => {
        output = output || {};
    
        console.log(" ");
        console.log(`Build Summary: ${inFile.toLowerCase()}`);
        console.log("---------------------------");
        return new Promise((resolve, reject) => {
            // prints output file name, size and gzip size.
            gulp.src(outFile).pipe(filesize({ enableGzip: true }))
                .on("error", reject)
                .on("end", () => {
                    // build rollup sumary.
                    const map = result.inlineMap || {};
                    if (Object.keys(map).length <= 0) console.log("No rollup optimizations performed.");
                    Object.keys(map).forEach((key) => {
                        console.log(`Rollup '${key}': ${(map[key] && map[key].length) || 0} optimizations.`);
                    });
    
                console.log("---------------------------");
                console.log(" ");
                resolve();
            });
        });
    });