Interested how Laravel works under the hood? → Check my Laravel Core Adventures Course

Front-end performance part 01 - Assets loading

#performance

I'm too old for this sh**.

This post has already become quite old, and a lot has changed in that field since I wrote it. The examples I provide might not work anymore or are not suitable for how we work today. Please be aware of that while reading it.

There are two major reasons for that. First developers often think performance is only about backend programming and there are other people who have to think about that. If an app is not performing well, it has to do with the logic built in programming languages like PHP or Ruby. Wrong! Performance starts with planning a project and ends served on the client's table. It is not something you can do simply after the work is done. Performance has to be considered during the whole project by everybody who is involved.

..this series will help you get started with it, improve your skills and will hopefully make you a better developer.

The other reason why performance isn't always popular among developers is because they think it is complex and difficult to maintain. Wrong again! Ok this time it is not that wrong. Performance is complex and most of the time very technical. But guess what? Big surprise: we are engineers. We have to deal with performance in some way and we need to know how things work in the Internet in order to make our products faster and become a better developer. So here is the good news. You do not have to become an expert on speed immediately. I am just saying you have to start dealing with performance now because it is a deciding factor for usability, user experience and search engines too. This series will focus on front-end performance. We will deal with everything between sending requests and displaying what we get back. We will not talk about how to make server side code performing well and I will not go into detail with every technique. As I already mentioned performance can be a very huge and complex topic and this series will help you get started with it, improve your skills and will hopefully make you a better developer.

So what have we got so far?

  • performance is important
  • regardless what kind of developer your are, you have to deal with it
  • performance is a huge and complex topic, but you can start slow and there are a lot of people here to help you

Understanding Browsers

Before we can start improving things, we need to know what is happening between us typing a url and receiving a website. Yeah of course you probably know a bit about DNS or HTTP requests, but we need to figure out how a browser is working. Important is how the browser handles HTML and CSS. This is done progressively. He is going to render things as they come. For example if the browser renders the body element it will immediately apply styles to it, but only if it already got them. This is because the browser tries to avoid redraws of element. Modern ones are really clever and try to help us where they can. But it is important to understand their behavior in order to support them. Another important fact is that some resources can block others. While styles are applied on HTML selects, rendering is blocked. JavaScript blocks rendering the page too. This is because JS can change elements and therefor has to be fully loaded before next elements are rendered. Additionally a script can depend on another one.

<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js">
<script type="text/javascript" src="http://yourdomain.com/js/main.js">

In this case jQuery needs to be fully loaded, so that min.js can make use of it. Pretty clear.
Another interesting fact is that browser try to load as many assets as possible parallel from one domain. Again JavaScript will block this functionality here in order not to mess things up, as mentioned above.

This was a really really short overview on what we have to know about browsers.

Take with you these things:

  • browsers are very clever
  • they work progressively
  • assets can be loaded parallel
  • some assets can block others

Improving assets handling

Now that we know what browsers do, we can take advantage of that. We said they can load a specific amount of assets parallel. We also mentioned that this amount refers to a domain. That means if we recieve assets from different domains, we can load more assets parallel. But how can we do that? It's probably easier than you might think.

<img src="images/img.png" alt="your image">
<img src="http://subdomain.yourdomain.com/images/img2.png" alt="your image">

The only disadvantage is that the additionally DNS lookup will take some time too. So what is that? It is the time it takes to translate a domain name to an IP address. If a user has never been to your site, he has to lookup www.yourdomain.com. In average this lookup will take about 130 milliseconds and is necessary for your standard domain. If your are using a subdomain like subdomain.yourdomain.com for serving assets you have to be careful that it is worth the additionally time. In most cases this will help improving your site performance only on bigger project with lots of assets. For this purpose modern browsers support HTML5 DNS prefetching. This is simple but very useful.

<link href="//another-domain.com" rel="dns-prefetch" />

This link element will tell browsers that we are going to load something from another domain. They are now able to do the lookup right before the asset is needed in order to decrease the delay. This is really awesome, but is not working in all browsers. Furthermore it is not working with HTTPS for security reasons. But overall totally worth it and you see results instantly. This is how I use it on christoph-rumpel.com:

Without Prefetching DNS Prefetching Google Analytics

In the first waterfall graph you can see that loading Google Analytics takes up 183 milliseconds. With DNS prefetching (second image) the lookup is done half a second before the resource is needed and the actually load time is now only 123 milliseconds. Awesome!

Besides that it is also possible to prefetch other assets, for example images. Normally they are downloaded when they are need in HTML as img tag or as CSS rule. Harry Roberts
is serving his spites early in HTML:

<img alt="icons" src="/img/css/sprites/main.svg" />

Images are fetched earlier by the browser if they appear in HTML, even when they are not displayed. Now when the sprites are actually needed by CSS, the image is already loaded. There is also a link tag for that similar to what we have seen before with prefetching DNS.

<link href="http://yourdomain.com/images/sprite.png" rel="prefetch" /> //FIREFOX
<link href="http://yourdomain.com/images/sprite.png" rel="prerender" /> //CHROME

As far as I can tell Firefox is using the rel attribute "prefetch" and Chrome "prerender". The name lets us already assume that they work differently too. For example if we prefetch a html page, it will not already load the assets. Google's Chrome will do that. This can be very useful when you already know where the user will go next. If you have an article with pagination, it is obviously a good idea to prerender the next page or upcoming images in a gallery. Unfortunately it is not clear how the browser will work with prerender or prefetch in detail. There are some different opinions on that. I have tried to test the effects too, but they were not measurable for me. If you have any more informations regarding this behavior, I would love to hear about that.

no request is faster than no request (Ilyia Grigorik)

Next good thing to improve assets handling is to GZIP them. I hope this is something that most of you have heard of already. Since most of our assets are text files (HTML, CSS, fiJavaScript, etc.) it is easy to compress them effectively. GZIP compression is done by your server and that is why you have to check if you can turn it on. But on some clever hosting companies it is already turned on for you. So let us check that out quickly by filling in your domain here. If it is on great, if not, you may talk to your host. In most cases you can enable it by yourself in a .htaccess like shown here.

Keep these things in mind:

  • browser are clever but we can help them dealing with assets even better
  • delivering assets from different domains is great for bigger projects
  • do DNS prefetching
  • memorize that there is also prefetching for assets
  • GZIP

Cleaning Up HTML

No we go into detail with our assets and start with HTML. We already know how browsers deal with our assets, so let us take advantage of that. You have probably heard of "styles up top and scripts at the bottom" and your probably tried to keep your structure that way without knowing why. Because I did not know the reasons for doing it that way, it happened that some scripts ended up in the head section. I just thought it wasn't a big deal. And that's ok if you want to stop improving your skills and help make the web slow and awful place. Seriously it is a big deal, just because performance is a big deal. The reason why we want our styles at the top is, that the browser needs them as soon as possible. If there are styles at the bottom the browser will start rendering without them. The reason why Scripts belong to the bottom (by bottom I mean before the closing body tag) is because as already mentioned they block other assets while they are loaded. When we put them at the bottom, the browser will render the HTML and CSS much faster. So from now on you will do it the right way and you will know why. In order to load your HTML even faster you can minify it. This will remove all the unnecessary line break and spaces. There are some online tools out there for minifying HTML like this. Additionally it is a good idea to load scripts form 3rd parties asynchronously. We now know that scripts block rendering of the page, but when we set the boolean attribute "synch" we can tell the browser not to block other files. Another advantage is that our page will not be effected if a third-party site is slow or eventually down. With the boolean attribute "defer" we make sure our scripts are executed after DOM elements have finished loading. This is an alternative to document-ready functions. Our beloved Chris Coyer from CSS Tricks has written a little summary of all you have to know about "Thinking Async".

So do not forget:

  • styles up, scripts down
  • combine and minify
  • thinking async

CSS, walking the critical path

Because HTML and CSS are needed as soon as possible by the browser, this part of page rendering is called the critical path. This is where we need to be fast. Especially because all CSS styles are being loaded before rendering the page. For example your CSS rules for mobile devices are being loaded on desktop devices as well and vice versa. And yes print styles too! Some browsers can check better than others if assets like stylesheets are needed or can be loaded later, but overall keep in mind that it is crucial to server them as fast as we can. Again it is a good idea to combine CSS files for saving HTTP requests, as well as minifying files. I know some people, like me, want to separate their stylesheets in order to clean things up, but there are other ways for that. Using the @import rule to include other files is even worse. This is because the stylesheets cannot be downloaded parallel and the file with the @import rules has to wait for the file that is being included before going on. So if you NEED to user different stylesheet, please use the link tag. But I definitely would recommend using as CSS Preprocessor. It makes writing styles so much easier and faster. Additionally you are able to work in different files and let the CSS Preprocessor take care of combining and minifying them. Just awesome!

Keep in mind:

  • serve CSS as fast as you can
  • combine and minify
  • do not use @import rule
  • use a CSS Preprocessor

JavaScript, level up<

As we already mentioned, get yourself familiar with loading scripts asynchronously. We do not want scripts to block rendering the page and we do not want JavaScript to redraw elements unnecessarily. This is why we put our scripts at the bottom of the HTML body. Like with CSS we want to combine and minify our files in order to save up HTTP requests and time. When I write about JavaScript, I have to mention jQuery too. We all know and love it for making scripting so much easier and faster, but we have to be careful. We trust jQuery blindly without thinking about what we need it for. It is library and not a small one. This means we have and additional HTTP request and loading time. This is why the first rule is: do not use jQuery! People tend to use jQuery just because it is less to write and easier to understand than vanilla JS. Important is to think about if you really need jQuery for what you do. But no worry. I have been there too and i have used jQuery because selecting elements is that easy. But let's face it, it isn't that complicated in plain JavaScript as you can see:

var el = document.querySelector(".myclass");

On this site you can see how to use common jQuery functions in plain Javascript. Of course there a lot of scenarios where you definitely need jQuery and that is ok. Just make sure to follow some rules. First is to use the latest version, but do not automatically load it like here:

http://code.jquery.com/jquery-latest.js

This way you have to test every new version with your site. If there is a new version out, grab it and test it. If everything works fine, perfect. If not, fix it or go back to a previous version.
Regardless of whether you use a JS framework or not, you can improve performance through within the code you write. An interesting example is the for loop.

var arr = new Array(1000),
    len, i;

for (i = 0; i &lt; arr.length; i++) {
  // Bad - size needs to be recalculated 1000 times
}

for (i = 0, len = arr.length; i &lt; len; i++) {
  // Good - size is calculated only 1 time and then stored
}

Here you can see that for a normal for-loop JS will calculate the length of the array every time, if you do not store it in a variable. I am sure we all have been iterating arrays this way, without knowing why this is bad practice. So always think about performance while you code too.

Keep in mind here:

  • thinking async
  • combine and minify
  • think about not using jQuery
  • improve your code

Conclusion

This was part one of the series front-end performance where we took a look at assets handling. Now you are able to start improving your projects and help make the web a faster and better place. In the next part of this series we will go through all the beste practices for optimizing images which plays another big role in web performance.

Resources

Online Testing

Browser Extensions Further reading

Do you enjoy my posts?

Sign up for my newsletter to receive updates on my latest content.

You will receive monthly updates on my latest articles and products. I do care about the protection of your data. Read my Privacy Policy.