Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Front End Web Efficiency
The Top Ten

TJ VanToll

About Me

The Front End

Why should you care about performance?

Where to start?

Making a site fast may seem complex.

Practicality

There is a lot of bad information out there. These things are very rarely a bottleneck:

The Practical Top 10 List

Where does the list come from?

Lots of bad 3G experiences.

Let's Get Started

#1) Reduce HTTP Requests

The majority of loading time is spent downloading the various components that make up a web page - images, CSS, JavaScript, etc.

RTTs > Size

Download Times

Compare that to download numbers.

Page Size

According to the HTTP archive the average web page size in 2011 was 965 kb (Source).

Connections

Moral of the Story

Lots of small downloads = slow

How do you reduce HTTP requests?

Combine Things!

JavaScript

There are a plethora of options. Incorporate one into your workflow (source control hook, build script, release, etc...)

CSS

Images

Images Continued

Don't use images to make things that can easily be made in CSS. If you want a rainbow circular ball with shadows, make it with CSS.

Don't worry, old IE users don't need rainbow balls.

How to Measure

Chrome Dev Tools' network tab. You can see the number of requests, filter by request type, as well as view download and latency times.

That was a long #1.

Questions?

#2) Implement Caching

Browsers and Caching

Expires & Cache-Control

Specify how long the browser can use the cached resource without checking to see if a new version is available (Source).

The only difference between the two is syntax options; it's redundant to specify both. Set a far future expiry using one of these headers on everything not dynamic.

Expires & Cache-Control - Setting

Using Apache? Use the .htaccess from the HTML5 Boilerplate to get useful snippets (full source). For example:

# CSS and JavaScript
  ExpiresByType text/css                  "access plus 1 year"
  ExpiresByType application/javascript    "access plus 1 year"

Not using Apache? There are examples for other server configurations here.

Before you get started...

HTTP Headers - Strong

Bust the Cache

Cache Busting

Browsers cache based off full URL paths. Therefore, you can change the path whenever you want to bust the cache. This is easily done server side.

For example:

<!-- Inject a version number using a server-side templating language of your choice -->
<script src="/path/to/foo.js?version=1.2.3"></script>
<script src="/path/to/1.2.3/foo.js"></script>

Last-Modified

Questions?

#3) Optimize Images

Compress!

Compression

There are numerous lossless compress algorithms you can simply run against your code base. There are Windows, OS X, Linux, and free web based optimizers out there, but here are a few examples:

Tip #1

Don't scale images in HTML / CSS.

<img src="image1.jpg" height="100" width="100" />
<img src="image2.jpg" />
<style>
	[src='image2.jpg'] { height: 100px; width: 100px; }
</style>

For both images above a 100 x 100 pixel image will be displayed on the screen, but for both the full size image will be downloaded from the server. Resize the image on the server instead.

Tip #2

#4) Optimize 3rd Party Dependencies

Defer Loading

Loading of 3rd party scripts should always be deferred until after the DOM has loaded (i.e. after the DOMContentLoaded event has fired).

<-- Simple download of a script from Twitter, WHAT COULD GO WRONG? -->
<script src="//platform.twitter.com/widgets.js" ></script>

THE TWITTER IS DOWN!

Blocking Scripts

Browsers block for JavaScript execution because it could potentially affect the HTML parser (think document.write). Fix? Use the defer and async attributes.

<script src="//platform.twitter.com/widgets.js" async ></script>

defer and async

defer: Script execution will be delayed until HTML parsing is complete.

async: Script execution will occur whenever the resource becomes available, regardless of whether HTML parsing is available.

Nice visualization of the difference.

Social Buttons

#5) Gzip

Gzip = Big Deal

jQuery 1.8.2 goes from 93K --> 32K after GZip compression. Gzip is a big deal.

Gzip: How to use it?

Red: Browser tells web server is accepts gzipped resources.

Blue: Web server returns a gzip encoded JavaScript resource.

Gzip Continued

Ensure your web server is setting the Content-Encoding header appropriately.

HTML5 boilerplate's .htaccess includes the configuration for Apache servers.

#6) Use a CDN

CDN

Examples

Google Maps uses multiple domains to workaround the browser's connection per hostname limit.

When Yahoo moved static content from application servers to a CDN they saw end-user response time improvements of 20% or more (Source).

#7) Placement of Resources

CSS on Top

JavaScript on the Bottom

Make CSS and JS External

Ultra Optimization

#8) The DOM is a Mess

Which is faster? By how much?

Option 1:

var foo = document.getElementById('foo');
for (var i = 0; i < 1000; i++) {
	foo.innerHTML += 'a';
}

Option 2:

var foo = document.getElementById('foo');
var html = '';
for (var i = 0; i < 1000; i++) {
	html += 'a';
}
foo.innerHTML = html;

1000 times faster!?

Run it yourself

Why is the DOM Slow?

The browser has to do A LOT whenever the DOM is changed.

What to do?

#9) Delegate

Example

Turn all table cells red on hover.

var cells = document.getElementsByTagName('td');
for (var i = 0; i < cells.length; i++) {
	cells[i].addEventListener('mouseover', function(event) {
		event.target.style.backgroundColor = 'red';
	}, false);
}

//With jQuery
$('td').bind('mouseover', function() {
	$(this).css('backgroundColor', 'red');
});

One event per DOM node. More events firing leads to a slower user experience if the event is doing something non-trivial. More events attached leads to more memory consumption.

Better

var tables = document.getElementsByTagName('table');
for (var i = 0; i < tables.length; i++) {
	tables[i].addEventListener('mouseover', function(event) {
		if (event.target.nodeName == 'TD') {
			event.target.style.backgroundColor = 'red';
		}
	}, false);
}

//Or with jQuery
$('table').on('td', 'mouseover', function() {
	$(this).css('backgroundColor', 'red');
});

Less events means less memory consumption and a faster user experience.

#10) Honorable Mentions

Tools

Questions?

Make Users Happy

Thanks!

@tjvantoll

Use a spacebar or arrow keys to navigate