SlideShare a Scribd company logo
1 of 35
Download to read offline
MITIGATING ADVERTISEMENT IMPACT
ON PAGE PERFORMANCE by Ismail Elshareef
Friday, October 22, 2010
ISMAIL
ELSHAREEF
Edmunds, Inc.
@codeish
@EdmundsLabs
Friday, October 22, 2010
EDMUNDS, INC.
Online since 1995
Properties:
150M+ page views/month
Revenue = Ads + Leads
Friday, October 22, 2010
IN 2008 ... A VISION WAS BORN
Friday, October 22, 2010
REDESIGN OBJECTIVES
PERFORMANCE
(Page onLoad in < 1.5 sec)
RICHER CONTENT
(Flash, video, slicker UXD, ...etc)
BETTER REVENUE
(Only positive impact on ad impressions)
Friday, October 22, 2010
OUR DILEMMA
3rd-PARTY CODE PERFORMANCE
UXD
Friday, October 22, 2010
Fast WITHOUT
3rd
Party
Fast WITH 3rd
Party Code
Friday, October 22, 2010
• Fixed width/height
• Easy to late-load
• Sandboxed Code
iFrame JavaScriptOR
• Cannot lazy-load
• Access to DOM
• Richer Content
FORMS OF 3RD
-PARTY CODE
• Disadvantage
• Advantage
Friday, October 22, 2010
MISSION:
CONTROL 3RD
-PARTY JS
Friday, October 22, 2010
INITIAL ATTEMPTS
applies to 3rd
-Party JavaScript Code ONLY
Override document.write
iFrame’n’Copy
Friday, October 22, 2010
INITIAL ATTEMPTS
applies to 3rd
-Party JavaScript Code ONLY
Override document.write
iFrame’n’Copy
WE LEARNED THAT ...
3rd-Party JS Code should be treated as
Friday, October 22, 2010
(I) CAN’T CONTROL IT ALL
(II) SPEED UP WHAT YOU CAN
(Your code and lazy-loadable code)
(III) DEFER THE REST
(All code that cannot be lazy-loaded)
OUR NEWFOUND CREED
Friday, October 22, 2010
JAVASCRIPT
LOADER
Friday, October 22, 2010
3RD
-PARTY
HANDLING
LOGIC
A
Is this an ad?
Is this a JS
ad?
Is this a JS
module?
NO
YES
Create
placeholder
markup
NO
Request JS file
after loader is
included
B
Create iframe
placeholder
markup
YES
NO
Add JS chunk to
Loader loading the
iframe after page
load event
Create
placeholder
markup
Request JS file
after loader is
included
B
Create iFrame
placeholder
markup
Lazy-load iFrame
with JS Loader
YES
DONE
DONE
Friday, October 22, 2010
3RD
-PARTY
JAVASCRIPT
HANDLING
LOGIC
B
JS
Components?
DONE
NO
load in a hidden DIV
YES
.html?
disableallthird
party=yes
.html?
disableallads=
yes
.html?
disableadnum
ber=[int]
YES
is ad?
NO
NO
YES
YES
NO
is ad
position ==
[int]?
YES
YES
<script> is done loading
move content to
placeholder (collapse
when appropriate)
NO NO
Friday, October 22, 2010
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
queue: {high:[], normal:[], low:[]},
addModule: function(mod) {
if (PAGESETUP.modules[mod]) {
++PAGESETUP.modules[mod];
} else {
PAGESETUP.modules[mod] = 1;
}
},
execControls: function(start) {
if (!this.merged) {
this.merged = PAGESETUP.queue.high;
this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low);
}
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
queue: {high:[], normal:[], low:[]},
addModule: function(mod) {
if (PAGESETUP.modules[mod]) {
++PAGESETUP.modules[mod];
} else {
PAGESETUP.modules[mod] = 1;
}
},
execControls: function(start) {
if (!this.merged) {
this.merged = PAGESETUP.queue.high;
this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low);
}
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
queue: {high:[], normal:[], low:[]},
addModule: function(mod) {
if (PAGESETUP.modules[mod]) {
++PAGESETUP.modules[mod];
} else {
PAGESETUP.modules[mod] = 1;
}
},
execControls: function(start) {
if (!this.merged) {
this.merged = PAGESETUP.queue.high;
this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low);
}
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
!"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
queue: {high:[], normal:[], low:[]},
addModule: function(mod) {
if (PAGESETUP.modules[mod]) {
++PAGESETUP.modules[mod];
} else {
PAGESETUP.modules[mod] = 1;
}
},
execControls: function(start) {
if (!this.merged) {
this.merged = PAGESETUP.queue.high;
this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low);
}
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
!"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7
HOW DOES THE LOADER WORK?
- Loads global core libs (with YUI libs)
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
queue: {high:[], normal:[], low:[]},
addModule: function(mod) {
if (PAGESETUP.modules[mod]) {
++PAGESETUP.modules[mod];
} else {
PAGESETUP.modules[mod] = 1;
}
},
execControls: function(start) {
if (!this.merged) {
this.merged = PAGESETUP.queue.high;
this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low);
}
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
!"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7
HOW DOES THE LOADER WORK?
- Loads global core libs (with YUI libs)
- Executes JS chunks in priority in 25 ms intv.
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
queue: {high:[], normal:[], low:[]},
addModule: function(mod) {
if (PAGESETUP.modules[mod]) {
++PAGESETUP.modules[mod];
} else {
PAGESETUP.modules[mod] = 1;
}
},
execControls: function(start) {
if (!this.merged) {
this.merged = PAGESETUP.queue.high;
this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low);
}
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
!"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7
HOW DOES THE LOADER WORK?
- Loads global core libs (with YUI libs)
- Executes JS chunks in priority in 25 ms intv.
- Has debugging features ?jsflag=full
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
queue: {high:[], normal:[], low:[]},
addModule: function(mod) {
if (PAGESETUP.modules[mod]) {
++PAGESETUP.modules[mod];
} else {
PAGESETUP.modules[mod] = 1;
}
},
execControls: function(start) {
if (!this.merged) {
this.merged = PAGESETUP.queue.high;
this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low);
}
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments.callee, 10);
}
item.call();
}, 0);
},
addControl: function(fn, priority) {
switch(priority) {
case 'high':
this.queue.high.push(fn);
break;
case 'low':
this.queue.low.push(fn);
break;
case 'normal':
default:
this.queue.normal.push(fn);
break;
}
}
};
//]]>
</script>
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
!"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7
HOW DOES THE LOADER WORK?
- Loads global core libs (with YUI libs)
- Executes JS chunks in priority in 25 ms intv.
- Has debugging features ?jsflag=full
- Ability to exclude 3rd party code
Friday, October 22, 2010
WHY CREATE OUR OWN LOADER?
Run JS chunks in order of priority
Allow a Debug Mode
Decouple from DOM events
Friday, October 22, 2010
3RD
-PARTY CODE WITH JS LOADER
Lazy-load in desired priority
iFrames JavaScriptOR
Include after Loader include
<iframe id=”ad1” width=”300”
height=”250”>
// add JS chunk to loader
...
...
...
<script src=”loader.js”></script>
// execute JS chunk through loader
</body>
<div id=”ad2”></div>
...
...
...
...
...
<script src=”loader.js”></script>
// Handle JavaScript ads
</body>
Friday, October 22, 2010
With Ads
Without Ads
INSIDELINE.COM STATS
Friday, October 22, 2010
ANOTHER VISION WAS BORN
Friday, October 22, 2010
HTTP REQUESTS
0
50
100
150
200
Homepage New Cars Used Cars
Legacy Site Beta Site
152 135 111
44 72 44
Friday, October 22, 2010
PAGESPEED SCORES
0
22.5
45
67.5
90
PageSpeed
Legacy Site Beta Site
8765
Friday, October 22, 2010
INITIAL RESULTS
17%Total PageViews Per Session
Friday, October 22, 2010
(I) CAN’T CONTROL IT ALL
(II) SPEED UP WHAT YOU CAN
(Your code and lazy-loadable code)
(III) DEFER THE REST
(All code that cannot be lazy-loaded)
AGAIN ... OUR NEWFOUND CREED
Friday, October 22, 2010
WE ARE HIRING!
http://www.edmunds.com/help/about/jobs/
Friday, October 22, 2010
THANK YOU!
ISMAIL ELSHAREEF
Edmunds, Inc.
WE ARE HIRING!
http://www.edmunds.com/help/about/jobs/
@codeish
@EdmundsLabs
Photo Credits:
http://farm3.static.flickr.com/2203/2498445479_064841a97d_o.jpg
http://jcreviews.files.wordpress.com/2010/03/battlestar-galactica.jpg
http://img.wallpaperstock.net:81/crossroads-in-life-wallpapers_10124_1600x1200.jpg
http://upload.wikimedia.org/wikipedia/commons/0/01/Stapler-swingline-red.jpg
Friday, October 22, 2010

More Related Content

What's hot

Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJSSylvain Zimmer
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Ismael Celis
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitRebecca Murphey
 
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperVenturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperJon Kruger
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace PatternDiego Fleury
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End DevsRebecca Murphey
 
Testable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScriptTestable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScriptJon Kruger
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UIRebecca Murphey
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeRebecca Murphey
 
HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranRobert Nyman
 
$q and Promises in AngularJS
$q and Promises in AngularJS $q and Promises in AngularJS
$q and Promises in AngularJS a_sharif
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queueAlex Eftimie
 
History of jQuery
History of jQueryHistory of jQuery
History of jQueryjeresig
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I thinkWim Godden
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
Electron: From Beginner to Pro
Electron: From Beginner to ProElectron: From Beginner to Pro
Electron: From Beginner to ProChris Griffith
 
HTML5 & The Open Web - at Nackademin
HTML5 & The Open Web -  at NackademinHTML5 & The Open Web -  at Nackademin
HTML5 & The Open Web - at NackademinRobert Nyman
 

What's hot (20)

Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development Toolkit
 
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperVenturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace Pattern
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
Testable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScriptTestable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScript
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UI
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
 
Dojo Confessions
Dojo ConfessionsDojo Confessions
Dojo Confessions
 
Booting Weblogic - OOW14
Booting Weblogic - OOW14Booting Weblogic - OOW14
Booting Weblogic - OOW14
 
HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - Altran
 
$q and Promises in AngularJS
$q and Promises in AngularJS $q and Promises in AngularJS
$q and Promises in AngularJS
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queue
 
History of jQuery
History of jQueryHistory of jQuery
History of jQuery
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Electron: From Beginner to Pro
Electron: From Beginner to ProElectron: From Beginner to Pro
Electron: From Beginner to Pro
 
HTML5 & The Open Web - at Nackademin
HTML5 & The Open Web -  at NackademinHTML5 & The Open Web -  at Nackademin
HTML5 & The Open Web - at Nackademin
 

Similar to Mitigating Advertisement Impact on Page Performance

Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup PerformanceJustin Cataldo
 
Paris js extensions
Paris js extensionsParis js extensions
Paris js extensionserwanl
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCpootsbook
 
[AngularJS] From Angular to Mobile in 30 minutes
[AngularJS] From Angular to Mobile in 30 minutes[AngularJS] From Angular to Mobile in 30 minutes
[AngularJS] From Angular to Mobile in 30 minutesGlobant
 
How to create a magento controller in magento extension
How to create a magento controller in magento extensionHow to create a magento controller in magento extension
How to create a magento controller in magento extensionHendy Irawan
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Eyal Vardi
 
Desenvolvendo Aplicativos Sociais com Rails 3
Desenvolvendo Aplicativos Sociais com Rails 3Desenvolvendo Aplicativos Sociais com Rails 3
Desenvolvendo Aplicativos Sociais com Rails 3Carlos Brando
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0Jeado Ko
 
HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine)
HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine) HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine)
HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine) Gabriele Gigliotti
 
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade ServerlessKatyShimizu
 
[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade ServerlessKatyShimizu
 
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...PHP Conference Argentina
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
 
Modern frontend development with VueJs
Modern frontend development with VueJsModern frontend development with VueJs
Modern frontend development with VueJsTudor Barbu
 
Pengenalan AngularJS
Pengenalan AngularJSPengenalan AngularJS
Pengenalan AngularJSEdi Santoso
 

Similar to Mitigating Advertisement Impact on Page Performance (20)

Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup Performance
 
JavaScript Refactoring
JavaScript RefactoringJavaScript Refactoring
JavaScript Refactoring
 
Paris js extensions
Paris js extensionsParis js extensions
Paris js extensions
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
[AngularJS] From Angular to Mobile in 30 minutes
[AngularJS] From Angular to Mobile in 30 minutes[AngularJS] From Angular to Mobile in 30 minutes
[AngularJS] From Angular to Mobile in 30 minutes
 
How to create a magento controller in magento extension
How to create a magento controller in magento extensionHow to create a magento controller in magento extension
How to create a magento controller in magento extension
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)
 
Desenvolvendo Aplicativos Sociais com Rails 3
Desenvolvendo Aplicativos Sociais com Rails 3Desenvolvendo Aplicativos Sociais com Rails 3
Desenvolvendo Aplicativos Sociais com Rails 3
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0
 
Angular 1.5 & ES6
Angular 1.5  & ES6Angular 1.5  & ES6
Angular 1.5 & ES6
 
HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine)
HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine) HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine)
HTML5 e CSS3 (slides della sessione tenuta al DIMI di Udine)
 
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
 
[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
 
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Modern frontend development with VueJs
Modern frontend development with VueJsModern frontend development with VueJs
Modern frontend development with VueJs
 
Pengenalan AngularJS
Pengenalan AngularJSPengenalan AngularJS
Pengenalan AngularJS
 

Recently uploaded

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 

Recently uploaded (20)

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 

Mitigating Advertisement Impact on Page Performance

  • 1. MITIGATING ADVERTISEMENT IMPACT ON PAGE PERFORMANCE by Ismail Elshareef Friday, October 22, 2010
  • 3. EDMUNDS, INC. Online since 1995 Properties: 150M+ page views/month Revenue = Ads + Leads Friday, October 22, 2010
  • 4. IN 2008 ... A VISION WAS BORN Friday, October 22, 2010
  • 5. REDESIGN OBJECTIVES PERFORMANCE (Page onLoad in < 1.5 sec) RICHER CONTENT (Flash, video, slicker UXD, ...etc) BETTER REVENUE (Only positive impact on ad impressions) Friday, October 22, 2010
  • 6. OUR DILEMMA 3rd-PARTY CODE PERFORMANCE UXD Friday, October 22, 2010
  • 7. Fast WITHOUT 3rd Party Fast WITH 3rd Party Code Friday, October 22, 2010
  • 8. • Fixed width/height • Easy to late-load • Sandboxed Code iFrame JavaScriptOR • Cannot lazy-load • Access to DOM • Richer Content FORMS OF 3RD -PARTY CODE • Disadvantage • Advantage Friday, October 22, 2010
  • 10. INITIAL ATTEMPTS applies to 3rd -Party JavaScript Code ONLY Override document.write iFrame’n’Copy Friday, October 22, 2010
  • 11. INITIAL ATTEMPTS applies to 3rd -Party JavaScript Code ONLY Override document.write iFrame’n’Copy WE LEARNED THAT ... 3rd-Party JS Code should be treated as Friday, October 22, 2010
  • 12. (I) CAN’T CONTROL IT ALL (II) SPEED UP WHAT YOU CAN (Your code and lazy-loadable code) (III) DEFER THE REST (All code that cannot be lazy-loaded) OUR NEWFOUND CREED Friday, October 22, 2010
  • 14. 3RD -PARTY HANDLING LOGIC A Is this an ad? Is this a JS ad? Is this a JS module? NO YES Create placeholder markup NO Request JS file after loader is included B Create iframe placeholder markup YES NO Add JS chunk to Loader loading the iframe after page load event Create placeholder markup Request JS file after loader is included B Create iFrame placeholder markup Lazy-load iFrame with JS Loader YES DONE DONE Friday, October 22, 2010
  • 15. 3RD -PARTY JAVASCRIPT HANDLING LOGIC B JS Components? DONE NO load in a hidden DIV YES .html? disableallthird party=yes .html? disableallads= yes .html? disableadnum ber=[int] YES is ad? NO NO YES YES NO is ad position == [int]? YES YES <script> is done loading move content to placeholder (collapse when appropriate) NO NO Friday, October 22, 2010
  • 16. HOW DOES THE LOADER WORK? Friday, October 22, 2010
  • 18. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP HOW DOES THE LOADER WORK? Friday, October 22, 2010
  • 19. var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP HOW DOES THE LOADER WORK? Friday, October 22, 2010
  • 20. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP HOW DOES THE LOADER WORK? Friday, October 22, 2010
  • 21. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? Friday, October 22, 2010
  • 22. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) Friday, October 22, 2010
  • 23. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) - Executes JS chunks in priority in 25 ms intv. Friday, October 22, 2010
  • 24. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) - Executes JS chunks in priority in 25 ms intv. - Has debugging features ?jsflag=full Friday, October 22, 2010
  • 25. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) - Executes JS chunks in priority in 25 ms intv. - Has debugging features ?jsflag=full - Ability to exclude 3rd party code Friday, October 22, 2010
  • 26. WHY CREATE OUR OWN LOADER? Run JS chunks in order of priority Allow a Debug Mode Decouple from DOM events Friday, October 22, 2010
  • 27. 3RD -PARTY CODE WITH JS LOADER Lazy-load in desired priority iFrames JavaScriptOR Include after Loader include <iframe id=”ad1” width=”300” height=”250”> // add JS chunk to loader ... ... ... <script src=”loader.js”></script> // execute JS chunk through loader </body> <div id=”ad2”></div> ... ... ... ... ... <script src=”loader.js”></script> // Handle JavaScript ads </body> Friday, October 22, 2010
  • 28. With Ads Without Ads INSIDELINE.COM STATS Friday, October 22, 2010
  • 29. ANOTHER VISION WAS BORN Friday, October 22, 2010
  • 30. HTTP REQUESTS 0 50 100 150 200 Homepage New Cars Used Cars Legacy Site Beta Site 152 135 111 44 72 44 Friday, October 22, 2010
  • 31. PAGESPEED SCORES 0 22.5 45 67.5 90 PageSpeed Legacy Site Beta Site 8765 Friday, October 22, 2010
  • 32. INITIAL RESULTS 17%Total PageViews Per Session Friday, October 22, 2010
  • 33. (I) CAN’T CONTROL IT ALL (II) SPEED UP WHAT YOU CAN (Your code and lazy-loadable code) (III) DEFER THE REST (All code that cannot be lazy-loaded) AGAIN ... OUR NEWFOUND CREED Friday, October 22, 2010
  • 35. THANK YOU! ISMAIL ELSHAREEF Edmunds, Inc. WE ARE HIRING! http://www.edmunds.com/help/about/jobs/ @codeish @EdmundsLabs Photo Credits: http://farm3.static.flickr.com/2203/2498445479_064841a97d_o.jpg http://jcreviews.files.wordpress.com/2010/03/battlestar-galactica.jpg http://img.wallpaperstock.net:81/crossroads-in-life-wallpapers_10124_1600x1200.jpg http://upload.wikimedia.org/wikipedia/commons/0/01/Stapler-swingline-red.jpg Friday, October 22, 2010