@philos_io
Performances & SEO in
AngularJS
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
Performances in AngularJS
Use ‘track by’ inside ng-repeat (Part 1)
1.2.X
<ul>
<li ng-repeat="book in vm.books">
<span>{{book}}</span>
</li>
</ul>
angular.module('bookstore', [])
.controller('BookController', function($timeout){
this.books = ["JavaScript", "Angular", "React"];
$timeout(() =>{
this.books.push('JavaScript');
}, 2000);
});
• JavaScript
• Angular
• React
JS.bin
Use ‘track by’ inside ng-repeat (Part 1)
1.2.X
<ul>
<li ng-repeat="book in vm.books">
<span>{{book}}</span>
</li>
</ul>
angular.module('bookstore', [])
.controller('BookController', function($timeout){
this.books = ["JavaScript", "Angular", "React"];
$timeout(() =>{
this.books.push('JavaScript');
}, 2000);
});
• JavaScript
• Angular
• React
• JavaScript
JS.bin
Use ‘track by’ inside ng-repeat (Part 2)
1.2.X
<ul>
<li ng-repeat="book in vm.books track by $index">
<span>{{book}}</span>
</li>
</ul>
angular.module('bookstore', [])
.controller('BookController', function($timeout){
this.books = ["JavaScript", "Angular", "React"];
$timeout(() =>{
this.books.push('JavaScript');
}, 2000);
});
• JavaScript
• Angular
• React
• JavaScript
JS.bin
Use ‘track by’ inside ng-repeat (Part 3)
1.2.X
• JavaScript
• Angular
• React
• JavaScript
<ul>
<li ng-repeat="book in vm.books track by $index">
<span>{{book.title}}</span>
</li>
</ul>
angular.module('bookstore', [])
.controller('BookController', function($timeout){
this.books = [
{title:"JavaScript"},
{title:"Angular"},
{title: "React"}
];
$timeout(() =>{
this.books.push({title:"JavaScript"});
}, 2000);
});
JS.bin
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
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
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>
Disable binding information
1.3.X
Docs
<div ng-app="bookstore" ng-controller="BookController as book" class="ng-scope">
<div ng-show="book.visible" class="ng-scope">
<span class="ng-binding">{{book.title}}</span>
</div>
</div>
angular.module('bookstore', [])
.config(($compileProvider) => {
$compileProvider.debugInfoEnabled(false);
});
Disable binding information
1.3.X
Docs
angular.module('bookstore', [])
.config(($compileProvider) => {
$compileProvider.debugInfoEnabled(false);
});
<div ng-app="bookstore" ng-controller="BookController as book">
<div ng-show="book.visible">
<span>{{book.title}}</span>
</div>
</div>
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);
});
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;
});
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
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>
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>
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
SEO in AngularJS
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…)
Solution?
• Build your own SEO engine
• Use a third-party solution
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="!">
Professional options for SEO
• Prerender
• getseojs
• brombone
• Seo4ajax
To Be Continued…
Performances & SEO in AngularJS

Performances & SEO in AngularJS

  • 2.
  • 3.
    Agenda ● Performance tipsin AngularJS ● Tools for measuring performance ● SEO in AngularJS ○ Build your own SEO engine with PhantomJS ○ Using a third-tiers tool ● More Tools ● Q&A
  • 5.
  • 6.
    Use ‘track by’inside ng-repeat (Part 1) 1.2.X <ul> <li ng-repeat="book in vm.books"> <span>{{book}}</span> </li> </ul> angular.module('bookstore', []) .controller('BookController', function($timeout){ this.books = ["JavaScript", "Angular", "React"]; $timeout(() =>{ this.books.push('JavaScript'); }, 2000); }); • JavaScript • Angular • React JS.bin
  • 7.
    Use ‘track by’inside ng-repeat (Part 1) 1.2.X <ul> <li ng-repeat="book in vm.books"> <span>{{book}}</span> </li> </ul> angular.module('bookstore', []) .controller('BookController', function($timeout){ this.books = ["JavaScript", "Angular", "React"]; $timeout(() =>{ this.books.push('JavaScript'); }, 2000); }); • JavaScript • Angular • React • JavaScript JS.bin
  • 8.
    Use ‘track by’inside ng-repeat (Part 2) 1.2.X <ul> <li ng-repeat="book in vm.books track by $index"> <span>{{book}}</span> </li> </ul> angular.module('bookstore', []) .controller('BookController', function($timeout){ this.books = ["JavaScript", "Angular", "React"]; $timeout(() =>{ this.books.push('JavaScript'); }, 2000); }); • JavaScript • Angular • React • JavaScript JS.bin
  • 9.
    Use ‘track by’inside ng-repeat (Part 3) 1.2.X • JavaScript • Angular • React • JavaScript <ul> <li ng-repeat="book in vm.books track by $index"> <span>{{book.title}}</span> </li> </ul> angular.module('bookstore', []) .controller('BookController', function($timeout){ this.books = [ {title:"JavaScript"}, {title:"Angular"}, {title: "React"} ]; $timeout(() =>{ this.books.push({title:"JavaScript"}); }, 2000); }); JS.bin
  • 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 orOne 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 orOne 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>
  • 13.
    Disable binding information 1.3.X Docs <divng-app="bookstore" ng-controller="BookController as book" class="ng-scope"> <div ng-show="book.visible" class="ng-scope"> <span class="ng-binding">{{book.title}}</span> </div> </div> angular.module('bookstore', []) .config(($compileProvider) => { $compileProvider.debugInfoEnabled(false); });
  • 14.
    Disable binding information 1.3.X Docs angular.module('bookstore',[]) .config(($compileProvider) => { $compileProvider.debugInfoEnabled(false); }); <div ng-app="bookstore" ng-controller="BookController as book"> <div ng-show="book.visible"> <span>{{book.title}}</span> </div> </div>
  • 15.
    Use ‘useApplyAsync’ tooptimize $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 Statelessfilters 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 Statelessfilters 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 filtersinside 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 insteadof 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 moretips • 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
  • 21.
  • 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…)
  • 23.
    Solution? • Build yourown SEO engine • Use a third-party solution
  • 24.
    Use case: Prerender.ioon 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="!">
  • 25.
    Professional options forSEO • Prerender • getseojs • brombone • Seo4ajax
  • 26.