AngularJS 2 deployed using Grunt

Tags

, ,

What s the idea?

the experience of developing a front end app or modules using Angular 2 in Typescript is great!  but when it comes time to deploy, I find myself with all these definition files and more under “node_modules”. Beside, I have this feeling that I shouldn’t deploy my “node_modules” folder to prod; well if U do not have that thought running in the back of your head U should.

A bit of background

When writing front end code using typescript, the tsconfig file “target” and “module” properties specify respectively the specification support the generated JavaScript files will adhere and how your module/app will be loaded.  common well established module loading patterns/specifications are AMD and CommonJS. UMD covers both thus U could export your modules however U prefer using either commonJS or AMD pattern and it would work using UMD. for more info bing.com or google.com.  SystemJs is a UMD implementation.  Now if U remember inside ur systemjs.config file (configuration file passed to SystemJs ), we specified the explicit path to each angular module js file our project depends on. systemjs.config file is always included inside the page before importing our modules/app mainly because it maps our module requirements (example : “@angular/core”) to an actual js file or package.  In most cases the js file would have an extension of umd.js which state that it is in conformance with UMD or plain js extension. Also, inside our  systemjs config file, we specified the rxjs folder root (rxjs package) to be queried for all things rx (utils, operators, observers and subscribers …).  Now all we need is a system that can bundle all these required js files into a single file.  SystemJs builder provides just that; a single-file build for SystemJS of mixed-dependency module trees Smile.  The nice thing with SystemJS builder is the fact that it can automatically walks up the dependencies chains.

steps

 

1) npm install babel-core

2) npm install grunt-systemjs-builder –save-dev

 

3) create your custom systemjs config file and name it however U like.

in my case It I gave it the name: systemjs_prod.config. here is an excerpt:


System.config({
    babelOptions: {
        presets: ['es2015']
    },
    paths: {
        'npm:': '../../node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
        // our app is within this folder
        app: '../../js/app-dir/',

        // angular bundles
        '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
        '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
        '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
        '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
        '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
        '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
        '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
        '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
        '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
        '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',

        // other libraries
        'rxjs':                      'npm:rxjs'
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
        app: {
            main: './main.js', // this is our generated file from src/main.ts
            defaultExtension: 'js'
        },
        rxjs: {
            defaultExtension: 'js',
            format: 'cjs'
        }
    }

});

4) create your grunt file (here an example)


module.exports = function(grunt){

    grunt.loadTasks("../../node_modules/grunt-systemjs-builder/tasks"); // grunt-systemjs-builder is not installed as a normal npm task accessible for anywhere

    grunt.initConfig({
        systemjs: {
            options: {
                sfx: true, //this one is required to not have dependance on SystemJs
                baseURL: "../../path-to-where-my-main.js or entry point file is located",
                configFile: "./path to my systemjs config file/systemjs_prod.config.js",
                minify: false, //to avoid naming issues
                build: {
                    mangle: false
                }
            },
            main_dist:{
                files: [{"src": "app","dest": "../../js/my-new-generated.min.js"}]
            }
        }
    });

    grunt.loadNpmTasks('grunt-systemjs-builder');

    grunt.registerTask('default', ['systemjs:main_dist']);

};

5) grunt –v –file /path-to-grunt-file-defined above/

6) finally, remove or comment out your reference to systemjs.config.js from your html as well as your initial Sytem.import(…). 

7) Add your my-new-generated.min.js file to your page script tags.

       Fin!