AngularJs, Grunt, Optimizations, Performance

Improving performance in production environment


By default, when we create data-bound elements, angular attaches additional information about the scope and the bindings to the DOM node, and then applying ng-binding CSS class to the data bound element. Debuggers (such as Batarang) and test frameworks (Like Protractor) requires this information to be able to run.

Let’s try it out by ourselves

We will setup a simple app with a controller and a directive with isolated scope.

HTML

<div ng-controller="myController">controller</div>
<isolated-scope data-binding="isolated scope"></isolated-scope>

JavaScript

app.directive('isolatedScope', function() {
  return {
   scope: {
     binding: "@binding"
   },
   template: "{{binding}}"
  };
});

app.controller('myController', function($scope) {
  $scope.location = "You are in a controller";
});

Next, if we’ll execute in the console:

angular.element(document.querySelector('div')).scope();

We will get the scope of our controller.

$ChildScope: null
$$childHead: null
$$childTail: null
$$listenerCount: Object
$$listeners: Object
$$nextSibling: Scope
$$prevSibling: null
$$watchers: null
$id: 2
$parent: Scope
location: "You are in a controller"

And if we try –

angular.element(document.querySelector('isolated-scope')).isolateScope();

We will get the isolated scope of the directive

$$childHead: null
$$childTail: null
$$destroyed: false
$$isolateBindings: Object
$$listenerCount: Object
$$listeners: Object
$$nextSibling: null
$$phase: null
$$prevSibling: ChildScope
$$watchers: Array[1]
$id: 3
$parent: Scope
$root: Scope
binding: "isolated scope"


OK, that’s informative. So what’s the problem?

The problem is, that according to Angular’s running in production document, this info may come at a cost of “significant” performance loss.

Luckily, the solution is quite simple. Since you need this information while developing and debugging, but you do want to turn it off in production,
you can easily switch it on/off in the config phase of the application, and control this configuration with your build tool. Let’s see an example –

First, we configure debugInfoEnabled during the config phase of our application.

// application's config constant
angular.module('myApp').constant('myConfig', {
	enableAngularDebugInfo: true
});

// setup necessary changes in config phase 
angular.module('myApp').config(function ($urlRouterProvider, myConfig) { 
  $compileProvider.debugInfoEnabled(myConfig.enableAngularDebugInfo);
});

The value enableAngularDebugInfo should be true by default, since we need it for development.
Next, we should disable it when building the application for production. I will demonstrate an example with Grunt, but you can do it with Gulp, Cake, Broccoli or any other task runner.

Configuring GruntFile to disable debugInfoEnabled in production

For simplicity purposes, i have removed from the GruntFile all commands that don’t directly relevant to disabling AngularDebugInfo:

module.exports = function (grunt) {

    // Project configuration.
    grunt.initConfig({
        'string-replace': {
            disableAngularDebugInfo: {
                options: {
                    replacements: [{
                        pattern: 'enableAngularDebugInfo: true,',
                        replacement: 'enableAngularDebugInfo: false,'
                    }
                    ]
                },
                src: 'temp/app.full.js',
                dest: 'temp/app.full.js'
            }
        }
    });

    // for build task, run string-replace.
    grunt.registerTask('build', ['string-replace']);
};

As you can see, we used the neat grunt-string-replace to replace true to false when running the build command. Obviously the actual build command will contain many more tasks (tests, jshint etc’), string-replace it’s only one of them.

And that’s it, now in your app.full.js file, angularDebugInfo will be disabled, so you can keep on developing while boosting up your applications performance in production environment.

6 thoughts on “Improving performance in production environment

  1. The amount of angular applications running in production while debug is on is too high, this really should be a common knowledge.

  2. Hi, I think this post is great, this is not said in many places! I’m using the same concept, but instead of modifying strings in the building process (I run tests in several built environments), I’m using ‘angular-environment’ package to detect my production environment. If so, I disable the debug info in the config stage. What do you think of this approach? And once again, congrats for this post!

    1. Hi, thanks ๐Ÿ™‚

      I think it’s really a situational decision and depends what works best in each case. For example, if the only difference between your production environment and dev environment is the debug info than it’s fine, but if in the future development environment will require additional resources and your assets aren’t lazy loaded, you may face additional costs for your servers. So again, no good-or-bad approach hear in my opinion, just situational decision.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s