More Related Content Similar to Mitigating Advertisement Impact on Page Performance Similar to Mitigating Advertisement Impact on Page Performance (20) Mitigating Advertisement Impact on Page Performance4. IN 2008 ... A VISION WAS BORN
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
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
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
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