21. Caching
Split your files up!
You will lose the benefit of caching
if constantly changing a large file
22. Lazy Load
• Defer the loading of JavaScript files until
they are needed
• Reduces the initial upfront requests
• Allows files to download asynchronously
• Use it to precache
23. How it works
LABjs (www.labjs.com) example
<script>
$LAB
.script("framework.js").wait()
.script("plugin.framework.js")
.script("myplugin.framework.js")
.wait(function(){
myplugin.init();
framework.init();
framework.doSomething();
});
</script>
24. Defer loading and precache
I don’t need this every time I visit
On first visit, lazy load the file in so I
have it in cache for when I need it
Load/execute the JavaScript when I
click on the link
25. Scripts at the bottom
• Custom tag called web:script
• Moves all scripts to the bottom
• Allows for lazy loading
• Compresses inline scripts using
YUICompressor
26. web:script
/***** Load External Script *****/
<web:script src="/script/Meetup/packed/EventDetails.js" />
/***** Load Inline Script *****/
<web:script>
Meetup.Copy.noMembersMarkedAttended = "<trn:message key="event.attendance.noMembersMarkedAttended">No
members have been marked attended</trn:message>";
Meetup.Copy.noMembersMarkedAttendedDynam = '<trn:message
key="event.attendance.noMembersMarkedAttendedDynam"><trn:param name="GROUPING">__GROUPING__</
trn:param>No members in "{GROUPING}" have been marked attended</trn:message>';
Meetup.Copy.noMembersMarkedAbsent = "<trn:message key="event.attendance.noMembersMarkedAbsent">No
members have been marked absent</trn:message>";
</web:script>
31. Do you really need all those photos to load?
• Only load what’s in the viewport
• Load the rest later
• On scroll
• After page loaded
32. How it works
return elements.each(function () {
var self = $(this),
src = self.attr('data-src'); // We set a data attribute for the image
self.one('appear',function() {
$('<img />').bind('load', function() {
self.hide().attr('src', src)[options.effect]
(options.effectspeed);
self.data('loaded', true);
var temp = $.grep(elements, function (item) {
return !$(item).data('loaded');
});
if (temp.length == 0) {
$window.unbind('scroll', load);
}
}).attr('src', src);
});
if (!isBelowFold(self, options)) {
self.trigger('appear'); // In viewport then show
} else {
self.data('loaded', false); // Else set loaded to false
}
});
33. Embed images
(If you can)
• Use Data-uri/MHTML
• Embeds the images in your code
• Reduces requests
• but increases file size
34. Use vector images
(If you can)
• Supported in all browsers
• raphael.js makes it easy
• Uses SVG and VML
39. DOM Monster
“DOM Monster is a cross-platform, cross-
browser bookmarklet that will analyze the
DOM & other features of the page you're on,
and give you its bill of health.”
40.
41. We have a case of divitis and
DOM Monster is the cure
42. Clean up your CSS
• Remove unused CSS
• Use efficient selectors
• Reduce CSS
43. Write efficient selectors
• Avoid a universal selector
• Uses classes or allow elements to inherit from ancestors
• Make your rules as specific as possible
• Use classes or IDs over tag selectors, allows for less traversal
• Remove redundant qualifiers
• body ul li a {...} - everything is always under body so we don’t need it
• form#myForm {...} ---> #myForm {...}
• Use classes instead of descendant selectors
• ul li {color: red} ---> .list-item-red {color:red}
• Avoid :hover on non-link elements for IE
• Use JS mouseover
http://code.google.com/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors
44. Use PageSpeed
http://code.google.com/speed/page-speed/
49. Let’s optimize this
function renderComments(data) {
for(var i = 0; i < data.length; i++) {
var comment = $(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’);
$(“#commentList”).append(comment);
};
};
50. Time it
function renderComments(data) {
console.time(“myloop”);
for(var i = 0; i < data.length; i++) {
var comment = $(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’);
$(“#commentList”).append(comment);
};
console.timeEnd(“myloop”);
};
51. Time it
function renderComments(data) {
console.time(“myloop”);
for(var i = 0; i < data.length; i++) {
var comment = $(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’);
$(“#commentList”).append(comment);
};
console.timeEnd(“myloop”);
};
3ms
52. Optimize
function renderComments(data) {
console.time(“myloop”);
var i = 0,
length = data.length;
for(i; i < length; i++) { // Evaluates data.length every time
var comment = $(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’);
$(“#commentList”).append(comment);
};
console.timeEnd(“myloop”);
};
53. Optimize
function renderComments(data) {
console.time(“myloop”);
var i = 0,
length = data.length;
for(i; i < length; i++) { // Evaluates data.length every time
var comment = $(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’);
$(“#commentList”).append(comment);
};
console.timeEnd(“myloop”);
};
2ms
54. Stop hitting the DOM!
function renderComments(data) {
console.time(“myloop”);
var i = 0,
length = data.length;
for(i; i < length; i++) {
var comment = $(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’);
$(“#commentList”).append(comment); // BAD
};
console.timeEnd(“myloop”);
};
55. Stop hitting the DOM!
function renderComments(data) {
console.time(“myloop”);
var i = 0,
length = data.length,
frag = document.createDocumentFragment();
for(i; i < length; i++) {
// Append off the DOM
frag.appendChild($(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’));
};
$(“#commentList”).append(frag); // GOOD
console.timeEnd(“myloop”);
};
56. Stop hitting the DOM!
function renderComments(data) {
console.time(“myloop”);
var i = 0,
length = data.length,
frag = document.createDocumentFragment();
for(i; i < length; i++) {
// Append off the DOM
frag.appendChild($(‘<li class=”comment” id=”’+data[i].id+’”>‘+data[i].comment+’</li>’));
};
$(“#commentList”).append(frag); // GOOD
console.timeEnd(“myloop”);
};
2ms
58. Mustache
• Use on the client or server side
• Makes generating html simple
• Logic-less
http://mustache.github.com/
http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-using-the-mustache-template-library/
65. Add context to selectors and cache them
Context
$("a.clickme").addClass("red"); //Not bad
$("#container").find("a.clickme").addClass("red"); //Better
$("#container a.clickme").addClass("red"); //Better
Cache Selectors
var clickmes = $("#container").find("a.clickme");
clickmes.addClass("red");