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.
The amount of angular applications running in production while debug is on is too high, this really should be a common knowledge.
Perhaps the reason is that it was added only since angular 1.3, not everyone following the release notes of every version
Thank you for sharing
You’re welcome ๐
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!
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.