performances & seo in angularjs
TRANSCRIPT
@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 binding1.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 binding1.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 information1.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 information1.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 filters1.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 filters1.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 markup1.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…