Shifting Gears

Post on 06-May-2015

9.650 views 2 download

description

My first talk at geekmeet Sweden, talking about basics of web site performance.

Transcript of Shifting Gears

Shifting your site into the next gear

Christian Heilmann | http://wait-till-i.com | http://twitter.com/codepo8

GeekMeet, Stockholm, Sweden, December 2008

htt

p:/

/ww

w.f

lick

r.co

m/p

ho

tos/

fab

iove

nn

i/91

7803

34/

Hello there...

I’m Chris.

It is great to be in Sweden...

...especially when you live in England...

Ok, I originally meant not to make any naughty jokes.

But then I saw the Adwords Robert seems to have bought

for GeekMeet.

... enough of this, let’s get serious ...

The performance of your web product is immensely important

And there are several small tricks and ideas that can

increase the performance significantly.

There is a lot of research being done on the subject in

a lot of companies...

...and this information is available for free for you.

I’ll provide the links and names later...

...but for now let’s see what is slowing our sites down.

Things that slow you down

http://www.flickr.com/photos/pikerslanefarm/2428232674/

<script>

JavaScript is awesome.

Browsers think so, too.

Which means that every time they encounter a script node

they take a break.

<script> </script>

Rendering stops and the JavaScript parser takes over.

If there is code inside the tag, this code is analyzed and

executed before the browser goes back to rendering.

If there is a src attribute, the file it points to gets loaded,

parsed and executed.

This can take time as the browser (with third party

files) needs to get the right domain information, contact the other server, get the file

and then move on.

This gets worse the more script nodes you use.

The first question is then where to put scripts?

The gospel according to Heilmann, 2006:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="se-se(bork bork)"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script type="text/javascript" src="myscripts.js"></script></head><body><!-- lots of HTML here --></body></html>

This has some benefits:

You can be sure your JavaScript is loaded before the document is displayed.

You make it easier for other developers to debug – they know where the scripts are.

On the other hand...

You delay the display of the page until all the scripts are

loaded and executed.

You need to delay the access to any HTML to change or

enhance until it is available – onload, onavailable, oncontentloaded.

This is hacky!

The gospel according to performance specialists

2007/2008:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="se-se(bork bork)"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title></head><body><!-- lots of HTML here --> <script type="text/javascript" src="myscripts.js"></script></body></html>

The benefits are:

Your scripts don’t delay the rendering of the HTML.

HTML is available for enhancing.

The problems:

You don’t put scripts where people normally expect

them.

The HTML is already available for people to interact with before you can apply your

enhancement voodoo.

The recipe for performance and usability success?

Of course you need testing on your apps and sites to find

your perfect solution...

But here are some ideas:

How about a mix of both?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="se-se(bork bork)"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script type="text/javascript" src="main.js"></script></head><body><!-- lots of HTML here --> <script type="text/javascript" src="secondary.js"></script></body></html>

You can even execute delayed without hacks.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="se-se(bork bork)"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script type="text/javascript" src="main.js"></script></head><body><!-- lots of HTML here --> <script type="text/javascript">doStuff()</script> <script type="text/javascript" src="secondary.js"></script></body></html>

The first script can set a class called js on the body of the

document.

Which allows you to define two styles, one for the non-

scripting version and one for the dynamic one.

In the dynamic one you hide the problematic elements

that could be activated prematurely.

Once the functionality has been added, add another

class that undoes this.

.js #buttons{ position:absolute; top:0; left:-6000px;}.jsloaded #buttons{ position:relative; top:0; left:0;}

CSS parsers are very fast!

What about the multiple scripts issue?

Chunking your JavaScript into several includes all doing one job at a time is a great idea to

keep your solutions maintainable.

<script type="text/javascript" src="config.js"></script><script type="text/javascript" src="base.js"></script><script type="text/javascript" src="effects.js"></script><script type="text/javascript" src="validation.js"></script><script type="text/javascript" src="widgets.js"></script>

This does not mean though that you need to add all of

them as single includes.

You can easily write a backend script that does that

for you:

<script type="text/javascript" src="/pack/config/base/effects/validation/widgets"></script>

Fun things to do in this script:

Run through JSLint.

Minify.

Replace all strings with an array lookup to stop IE from creating a string object for

each string.

Instead of doing this every time the page is loaded, you

can make it part of a build process.

And don’t forget to cache the result!

Get a script that does most of that from Ed Eliot:

http://www.ejeliot.com/blog/73

The other option is to be lazy.

Lazy loading is a concept to load dependencies only when

and if they are needed.

Your base.js could test for all the things that should

work...

...and if they do, create script nodes dynamically to load the other, chunkier parts.

This is a pretty nice idea as it only loads things when they

are needed...

...thus saving server traffic and diminishing loading time.

However, there are problems.

Asynchronous loading means you never know in which

order the loaded components come back to you...

There are a lot more issues, for example that you might block document.write() of bad code ads in your page.

What other things slow you down?

<img>

Images are what made the web what it is now.

Sure, linking text was a revolution.

But being able to get images on demand and store them

was something that triggered the “collector” in everyone.

Yeah, Pr0n.

Anyways, too many images slow down your site

immensely.

The reasons are the same delays you experience with

external scripts...

...except images don’t stop the rendering.

However only a few get loaded at a time...

...as the number of parallel connections of browsers is limited (with good reason)

Which means you should cut down on the amount of

images.

The best trick there is to use CSS sprites.

And again, Ed Eliot and Stuart Colville come to the rescue!

http://spritegen.website-performance.org/

You use Spritegen by uploading a zip of images...

...and it generates the CSS and the sprite image for you!

It is also open source in case you want to host it yourself.

How good are you in optimizing images?

Probably not as good as you think you are.

A lot of bytes can be squeezed out of images...

...without changing their visual outcome.

Choosing the right format in the right version can be quite

a drag.

And it doesn’t help that tools put all kind of pointless data into images (edited with xyz,

version abc...).

The easy way out?

http://smushit.com

What else could be a problem?

How about the amount of images on the page?

You can work around loading all the images by – once

again – delaying the loading.

The easy way is to prepend the images with a dummy

and then replace this.

<img src=”dummy.gif#kitten.jpg” alt=”a nice kitten”><img src=”dummy.gif#puppy.jpg” alt=”a nice puppy”>

<script type="text/javascript">window.onload = function(){

var imgs = document.getElementsByTagName(‘img’);for(var i=0;imgs[i];i++){var src = imgs[i].src;imgs[i].src = src.replace(‘dummy.gif#’,’’);

}}</script>

The more complex but cleverer way is to wait until

the images are in the viewport.

http://developer.yahoo.com/yui/imageloader/

You can see this trick in action at shine.yahoo.com

and YouTube.

It’d be cool if browsers did that anyways – anyone

remember lowsrc?

What else is slowing us down?

<object>, err <embed> err...

Flash and other plugins have the same issues as <script>

has.

You interfere with the browsers’ normal rendering

and they wait until the confusion is over.

The other issue of course is that making embedding work

and validate is a pain.

The solution for this is progressively enhancing

Flash embedding.

http://swfobject.googlecode.com

As you embed with JavaScript you can test for the correct

Flash support.

And you can delay the embedding by for example enhancing an image when

the user clicks on it.

SUMMARY TIME!

In general there are two things to do:

Collate and Delay :)

The tips and tools:

★ http://developer.yahoo.com/performance/★ http://www.stevesouders.com/★ http://website-performance.org/

★ YSlow: http://developer.yahoo.com/yslow/ ★ Hammerhead: http://stevesouders.com/hammerhead/

Christian Heilmann

http://scriptingenabled.org | http://wait-till-i.com

twitter/flickr: codepo8

THANSK!Svenska?