- Use one-time-bind on expressions ( {{::value}} )
- Replace
$scope.$apply()
with$scope.$digest()
whenever possible - Move filters to controllers
To get the total watchers on the current page, you can run this script on the browser console:
function getWatchers(root) {
root = angular.element(root || document.documentElement);
var watcherCount = 0;
function getElemWatchers(element) {
var isolateWatchers = getWatchersFromScope(element.data().$isolateScope);
var scopeWatchers = getWatchersFromScope(element.data().$scope);
var watchers = scopeWatchers.concat(isolateWatchers);
angular.forEach(element.children(), function (childElement) {
watchers = watchers.concat(getElemWatchers(angular.element(childElement)));
});
return watchers;
}
function getWatchersFromScope(scope) {
if (scope) {
return scope.$$watchers || [];
} else {
return [];
}
}
return getElemWatchers(root);
}
getWatchers().length
To get information of time that an operation takes, you use one of these two methods:
Run:
window.performance.mark('begin_operation');
Just before the operation starts. Then:
window.performance.mark('finish_operation');
When it ends. Then:
window.performance.measure('operation', 'begin_operation', 'finish_operation')
The result will be stored on:
window.performance.getEntriesByType('measure')[0].duration
The output is in miliseconds with microseconds units.
1- Go to you chrome Profiles tab on developer tools 2- Click on record 3- Do an specific operation 4- Pause recording
The idle time can be ignored, what we are looking for here is the program time.
You can see how much time every operation took and even some suggestion right away on what to improve (the exclamation marks).
You might have noticed that Angular addes a few classes like "ng-binding", "ng-scope", and a few others to your tags. This happen on compile time where, for debugging purposes, Angular attach those class. But it is also attaching the entire scope object to every element (which help us access any elemnt's scope via console with: angular.elemnt(<HTML NODE>).scope()
).
But that comes with a performance cost. A cheap way to speed up you Angular app, in the cases where you have several bindings, is to disable it like so:
app.config(['$compileProvider', function ($compileProvider) {
// disable debug info
$compileProvider.debugInfoEnabled(false);
}]);
You will not have acess to element's scope from the DOM, and protractor and Baratang will not work. For that reason, you will want to only enable it in production. But, even if in Production if you need to debug your app, you can call from the console: angular.reloadWithDebugInfo()
. Voialá! There you have you debug classes and scopes attached to elements again.
Reference: http://blog.thoughtram.io/angularjs/2014/12/22/exploring-angular-1.3-disabling-debug-info.html
https://docs.angularjs.org/api/ng/directive/ngModelOptions
By default, any change to a model will trigger an entire digest loop. For example, If you know a a field change can wait until the user leave the field, you can set ng-model-option to only update the model on blur event.