Search code examples
javascripttypescriptangularsystemjs

Angular2 bundling and minification


ASP.NET (or gulp) will take care of bundling and minification. However, the problem i came across is rather different. Per Angular2's tutorials, the view HTML is embedded within the component itself. There is a way, using TypeScript, to separate that into a .ts and .html files. Here's how:

...
/// <reference path="./view-declaration.d.ts" />
...
import {html} from '/app.html!text';
...
@Component({
    ...
    template: html
})
...

And faking .html as a module in view-declaration.d.ts file:

declare module '/app.html!text' {
    var html:string;
    return default html;
}

This is using SystemJS with its text plugin. This will not generate System.register for .html files which means HTMLs can't be bundled along the transpiled .js files.

So questions is, how do you separate the HTML from JavaScript, but also be able to bundle them properly?

Also to note, this approach is just the same as setting the templateUrl on your component. Both of which defeat the purpose of bundling and reduction of server hits per component. The offered solution from Angular2 is to use string and set template on a component. This is pretty far from reality of junior developers and code reviews (yea not gonna get the whole code base in order to run and see if browser complains about a non-closed tag!).


Solution

  • As it turns out, you'll need to use templateUrl for development, but replace that with template during the bundling and minification. This is the gulp task for the job:

    var gulp = require('gulp'); //install 'gulp' via npm
    var uglify = require('gulp-uglify'); //install 'gulp-uglify' via npm
    var concat = require('gulp-concat'); //install 'gulp-concat' via npm
    var replace = require('gulp-replace'); //install 'gulp-replace' via npm
    var fs = require("fs"); //already available in Visual Studio and of course NodeJS
    
    gulp.task('bundle:js', function () {
        return gulp
            .src([
                "file1.js",
                "file2.js"
            ])
            .pipe(replace(/templateUrl.*\'/g, function (matched) {
                var fileName = matched.match(/\/.*html/g).toString();
                var fileContent = fs.readFileSync(fileName, "utf8");
                return 'template:\'' + fileContent.replace(/\r\n/g, '') + '\'';
            }))
            .pipe(concat('file.min.js'))
            .pipe(gulp.dest('my bundle folder'))
            .pipe(uglify())
            .pipe(gulp.dest('my bundle folder'));
    });
    

    This is to match .html files and the template URL, but it can be tweaked if needed.