Skip to content

Instantly share code, notes, and snippets.

@amcdnl
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amcdnl/8865294 to your computer and use it in GitHub Desktop.
Save amcdnl/8865294 to your computer and use it in GitHub Desktop.

AngularJS + RequireJS Optimization

RequireJS is a great module loading tool and it has great optimization techniques. When you combine RequireJS with GruntJS you get some really powerful tools; but the AngularJS optimization is still somewhat lacking.

A few key tools you can leverage to make your AngularJS apps blazing fast and clean are:

ng-min

When writing AngularJS controllers/services/directives you often end up with a HUGE constructor to make the code optimizer safe. I ended up with something like this quite a bit:

return app.controller('WorkspaceCtrl', ['$rootScope', '$scope', '$route', 'DashboardModel', 'dashboards', 'reports',     'workspaces', '$modal', 'growl',
       function WorkspaceCtrl($rootScope, $scope, $route, DashboardModel, dashboards, reports, workspaces, $modal, growl){
        //.. controller code here ...
 }]);

Nasty right? This is where ng-min comes into play. ng-min will allow you to write:

return app.controller('WorkspaceCtrl', function($rootScope, $scope, $route, DashboardModel, dashboards, reports, workspaces, $modal, growl){
        //.. controller code here ...
 });

and at built time it will translate it to the above for you for correct compliation.

html2JS

Angular has powerful templating options, but they are loaded on demand. This can be optimal but if you are like me and have a ton of different templates nested and very modular this can kill your application performance.

html2js combined with grunt can scan your 'views' folder and create all the precomplied html templates for you in a single file utilizing Angular's templateCache. The end result is a file full of templates that look something like this:

angular.module("views/app.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("views/app.html",
    "<section class=\"main app\">....</section>");
}]);

Later I take that file templates.js and add it to the inital download of the app code.

GuntJS

Heres my GruntJS setup for the above options:

  module.exports = function(grunt) {

    grunt.loadNpmTasks('grunt-html2js');
    grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-wrap');

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        requirejs: {
            compile: {
                options: {
                    name: 'main',
                    out: 'app.min.js',
                    insertRequire: ['main'],
                    wrap: true,
                    separateCSS: true,
                    mainConfigFile: 'main.js',
                    preserveLicenseComments: false,
                    optimize: 'uglify2',
                    uglify2:{
                        mangle: false
                    },
                    include: ['lib/require/require'],
                    deps: ['templates'],
                    onBuildRead: function (moduleName, path, contents) {
                        return require('ngmin').annotate(contents);
                    },
                    pragmas: {
                        production: true
                    },
                    compile: {
                        options: {
                            paths: {
                                'templates':'empty:',
                            }
                        }
                    }
                }
            }
        },
        html2js: {
            main: {
                options: {
                    htmlmin: {
                        collapseBooleanAttributes: true,
                        collapseWhitespace: true,
                        removeAttributeQuotes: true,
                        removeComments: true,
                        removeEmptyAttributes: true,
                        removeRedundantAttributes: true,
                        removeScriptTypeAttributes: true,
                        removeStyleLinkTypeAttributes: true
                    },
                    base: './'
                },
                src: ['views/**/*.html'],
                dest: 'templates.js'
            }
        },
        wrap: {
            basic: {
                src: ['templates.js'],
                dest: 'templates.js',
                options: {
                    wrapper: ['define(["app"], function (app) {\n',
                        '\n app.requires.push("templates-main"); });']
                }
            }
        }
    });

    grunt.registerTask('default', ['html2js', 'wrap', 'requirejs']);
    
    return grunt;
  };

Type grunt and your app is optimized for awesomeness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment