Performance Optimization in AngularJS
Key Concepts
- Minification and Bundling
- Lazy Loading
- Tree Shaking
- Optimizing Directives
- Reducing Watchers
- Using One-Time Binding
- Optimizing Digest Cycle
- Caching Data
- Optimizing DOM Manipulation
- Using Batarang for Profiling
1. Minification and Bundling
Minification involves removing unnecessary characters from code to reduce file size. Bundling combines multiple files into a single file to reduce the number of HTTP requests.
Example:
// Before Minification function add(a, b) { return a + b; } // After Minification function add(a,b){return a+b;}
Imagine minification as packing a suitcase efficiently, removing all the air (unnecessary characters) to make it lighter and smaller.
2. Lazy Loading
Lazy loading defers the loading of non-critical resources until they are needed. This reduces the initial load time of the application.
Example:
angular.module('myApp', ['ui.router']) .config(function($stateProvider) { $stateProvider.state('lazy', { url: '/lazy', templateUrl: 'lazy.html', controller: 'LazyCtrl', resolve: { load: function($q, $ocLazyLoad) { var deferred = $q.defer(); require(['lazyModule'], function(lazyModule) { $ocLazyLoad.load(lazyModule); deferred.resolve(); }); return deferred.promise; } } }); });
Think of lazy loading as ordering food at a buffet. You only take (load) what you need (non-critical resources) when you need it, rather than taking everything at once.
3. Tree Shaking
Tree shaking is a technique that removes unused code from the final bundle. This reduces the size of the application and improves performance.
Example:
// Unused code function unusedFunction() { console.log('This function is not used'); } // Used code function usedFunction() { console.log('This function is used'); } usedFunction();
Consider tree shaking as pruning a tree. You remove the dead branches (unused code) to make the tree healthier and more efficient.
4. Optimizing Directives
Optimizing directives involves reducing their complexity and ensuring they are efficient. This includes minimizing DOM manipulations and reducing the number of watchers.
Example:
angular.module('myApp') .directive('myDirective', function() { return { restrict: 'E', template: '<div>{{message}}</div>', scope: { message: '=' }, link: function(scope, element, attrs) { scope.$watch('message', function(newVal) { element.text(newVal); }); } }; });
Think of optimizing directives as tuning a car. You fine-tune (optimize) each part (directive) to ensure the car (application) runs smoothly.
5. Reducing Watchers
Reducing the number of watchers in an AngularJS application can significantly improve performance. Watchers are used to monitor changes in scope variables.
Example:
// Before optimization $scope.$watch('variable1', function() { console.log('Variable 1 changed'); }); $scope.$watch('variable2', function() { console.log('Variable 2 changed'); }); // After optimization $scope.$watchGroup(['variable1', 'variable2'], function(newValues, oldValues) { console.log('Variable 1 or 2 changed'); });
Consider reducing watchers as simplifying a recipe. You combine similar steps (watchers) to make the process (application) more efficient.
6. Using One-Time Binding
One-time binding is a technique that binds a value to the view only once. This reduces the number of watchers and improves performance.
Example:
<div>{{::message}}</div>
Think of one-time binding as a one-time purchase. You buy (bind) an item (value) once and don't need to keep checking (watching) it for changes.
7. Optimizing Digest Cycle
The digest cycle is the process by which AngularJS updates the view when a model changes. Optimizing the digest cycle involves reducing the number of times it runs.
Example:
$scope.applyAsync(function() { // Code to run asynchronously });
Consider optimizing the digest cycle as managing a meeting. You reduce the number of unnecessary discussions (digest cycles) to make the meeting (application) more efficient.
8. Caching Data
Caching data involves storing the results of expensive operations so they can be reused without recalculating. This improves performance by reducing redundant work.
Example:
angular.module('myApp') .factory('dataCache', function($cacheFactory) { return $cacheFactory('dataCache'); }); angular.module('myApp') .controller('MyCtrl', function(dataCache, $http) { var cache = dataCache.get('myData'); if (cache) { $scope.data = cache; } else { $http.get('/api/data').then(function(response) { dataCache.put('myData', response.data); $scope.data = response.data; }); } });
Think of caching data as a library. You store (cache) books (data) so you can quickly retrieve (reuse) them without needing to go to the bookstore (recalculate) each time.
9. Optimizing DOM Manipulation
Optimizing DOM manipulation involves reducing the number of times the DOM is updated. This can be achieved by batching updates or using virtual DOM techniques.
Example:
angular.module('myApp') .directive('myDirective', function() { return { restrict: 'E', template: '<div ng-repeat="item in items">{{item}}</div>', link: function(scope, element, attrs) { scope.$watchCollection('items', function(newItems) { element.html(''); angular.forEach(newItems, function(item) { element.append('<div>' + item + '</div>'); }); }); } }; });
Consider optimizing DOM manipulation as painting a wall. You apply multiple coats (updates) at once to avoid having to repaint (update the DOM) frequently.
10. Using Batarang for Profiling
Batarang is a Chrome extension for AngularJS that provides tools for profiling and debugging AngularJS applications. It helps identify performance bottlenecks.
Example:
// Install Batarang and use it to profile your AngularJS application
Think of Batarang as a diagnostic tool for a car. It helps you identify issues (performance bottlenecks) and fix them to ensure the car (application) runs smoothly.