It is aimed for developers who already used AngularJS in their projects or who are planning to. Angular is a great framework that enables you to build awesome Single Page Application (SPA). However, as your application grows, you can encounter situations where your expectations regarding the speed and/or the SEO of your application are not met.
During this conference, we will show you how to build a fast and scalable application. We will also share with you the guidelines and the tools that you should be using to keep your app well referenced on search engines, even when it scales to millions of pages!
3. Agenda
● Performance tips in AngularJS
● Tools for measuring performance
● SEO in AngularJS
○ Build your own SEO engine with PhantomJS
○ Using a third-tiers tool
● More Tools
● Q&A
10. Use ‘track by’ inside ng-repeat (Part 4)
• Avoid using immutable data inside your collection
• Using track by will force the directive not to recreate the DOM template
• Avoid using ng-repeat with filters inline (more on this later)
1.2.X
11. Bind once or One time binding
1.3.X
<div ng-app="bookstore" ng-controller="BookController as vm">
<ul>
<li ng-repeat="book in vm.books track by $index">
<span>{{book.title}}</span>
</li>
</ul>
<br/>
<span>{{vm.watchers}}</span>
</div>
angular.module('bookstore', [])
.controller('BookController', function($timeout){
this.books = [{title:"JavaScript"},
{title:"Angular"}, {title: "React"}];
$timeout(() =>{
this.books.push({title:"JavaScript"});
this.watchers = getWatchers().length;
}, 20);
});
JS.bin
12. Bind once or One time binding
1.3.X
angular.module('bookstore', [])
.controller('BookController', function($timeout){
this.books = [{title:"JavaScript"},
{title:"Angular"}, {title: "React"}];
$timeout(() =>{
this.books.push({title:"JavaScript"});
this.watchers = getWatchers().length;
}, 20);
});
JS.bin
<div ng-app="bookstore" ng-controller="BookController as vm">
<ul>
<li ng-repeat="book in ::vm.books track by $index">
<span>{{::book.title}}</span>
</li>
</ul>
<br/>
<span>{{::vm.watchers}}</span>
</div>
15. Use ‘useApplyAsync’ to optimize $http calls
1.3.X
Docs
Configure $http service to combine processing of multiple http responses received at
around the same time via $rootScope.$applyAsync. This can result in significant
performance improvement for bigger applications that make many HTTP requests
concurrently (common during application bootstrap).
angular.module('bookstore', [])
.config(($httpProvider) => {
$httpProvider.useApplyAsync(true);
});
16. Stateful vs Stateless filters
1.3.X
Docs
By default, filters are stateless. This improvement has been added into Angular 1.3 but It
can break your application in few cases.
<div ng-app="bookstore">
<input type="text" ng-model="model">
{{'start' | state}}
</div>
angular.module('bookstore', [])
.filter('state', () => {
function state(value){
console.log('run filter');
return value + ' after filtering';
}
return state;
});
17. Stateful vs Stateless filters
1.3.X
By default, filters are stateless. This improvement has been added into Angular 1.3 but It
can break your application in few cases.
<div ng-app="bookstore">
<input type="text" ng-model="model">
{{'start' | state}}
</div>
angular.module('bookstore', [])
.filter('state', () => {
function state(value){
console.log('run filter');
return value + ' after filtering';
}
State.$stateful = true;
return state;
});
JS.bin
18. Avoid using filters inside your markup 1.2.X
• Filters will run twice per $digest loop
• Use $filter inside your controller to improve performance
• Migrate to Angular 1.3 or 1.4
JS.bin
angular.module('bookstore', [])
.controller('BookController', function($scope, $timeout){
this.title = "javaScript Rocks!";
$timeout(() => {
$scope.$digest();
}, 2000);
})
.filter('upperCase', () => {
return (value) => {
console.log('inside filter');
return value[0].toUpperCase()+ value.slice(1);
};
});
<div ng-app="bookstore" ng-controller="BookController as book">
{{book.title | upperCase}}
<input type="text" ng-model="book.author"/>
<br/>
<span>{{book.author}}</span>
</div>
19. Use ng-if instead of ng-show
The $digest loop will run even if the component is not visible.
JS.bin
<div ng-app="bookstore" ng-controller="MainController as main">
<button ng-click="main.toggle()">Toggle</button>
<div ng-show="main.visible">
{{main.title | myFilter}}
</div>
</div>
<div ng-if="main.visible">
{{main.title | myFilter}}
</div>
20. Tools and more tips
• Avoid injecting components if there are not needed
• Avoid using ng-repeat where possible
• Use $templateRequest to preload your template
• Avoid using ng-repeat with filters inline
• $scope.$apply() vs $scope.$digest()? => $scope.$digest()
• JSPerf for performance measurement
• example of setting up JSPerf
• Google Chrome Dev tools (Profiling tool)
• Angular Batarang
22. What is SEO?
• Stands for Search Engine Optimization
• Search engine bots will query your website
• Since your website is an SPA, bots won’t find anything but just markup.
• Impact every JS Frameworks (Angular, Ember, Backbone, Aurelia…)
24. Use case: Prerender.io on NodeJS
Client Side
angular.module('bookstore', [])
.config(($locationProvider) => {
$locationProvider.hashPrefix('!');
$locationProvider.html5Mode(true);
}]);
Server Side : NodeJS-Express
$ npm install prerender-node --save
$ app.use(require('prerender-node'));
// Set the key from prerender.io
<meta name="fragment" content="!">