Wednesday, March 12, 2014

Come Fast my "CSS & JS"

A slow loading web page wastes the precious time of so many visitors. The loading speed of a website depends on several factors, of which loading CSS & JS files in a web page has a huge impact. Unfortunately developers used to miss, since in local development server we may not smell this but while in production remote server, it drags the loading time.  If few minutes we spent on optimizing the loading, it will save several minutes of several people.

Let’s try how to optimize the loading time. From one of a website, taken the CSS & JS files & loaded in an empty html page.   We can see the loading time in Firebug
01_FullDownload1

Nearly 20 CSS/JS files are used & it leads to 20 connection requests. Most browsers are supporting 6 concurrent connections per host & so there will be a six parallel downloading of files.  Rest files will be in waiting mode. That may be the reason for long loading time. To minimize that, let’s try by combining all the CSS & JS files in a single file. (To merge several css/js files into a single file, we can use server side scripting languages)
The result is
02_Merged2
We were able to save some seconds. But still it is slow, may be due to the size of the content. To reduce the file content size, let’s minify both css & js.


03_MergedwithMin2
We have saved some file size & some seconds. But still slow, let’s try to compress further using gzip. We can do that in our web server. (Since we are using IIS, enabled “compression for static files” in IIS Manager).
Let’s refresh the browser & check

04_Gzip_MergedwithMin1
That’s better. We have saved nearly 4.5 seconds & also the bandwidth.

But while using as a merged single file, we may have other issue too. Of several files, there may be a frequent updating of a single file, which leads to a new version of entire merged file & it leads to download often, which ignores the browser cache advantage.
In such cases, hosting the static files in CDN (Content Delivery Network) servers is a better option. And also, linking files from multiple domains provide an advantage of parallel downloading. If we have 100 static files, we can host them in 4 different domains, like splitting the resources 25 per domain. We should not forget, linking multiple domains, will take some time for DNS lookup.  As a rule of thumb, make sure a domain serves at least 10 files.

Back to our case, let’s use a CDN server to download few files & check the download speed
05_MultiDomainCDN1
Yes, as expected it is saving the loading time.

Based on our project requirements, we should plan merging, compressing & hosting in other domains.

Now we are nearly done with initial page load. What happen, when the browser navigate to the next page?  Are the files will download again for each page or browser cache will rescue us. Let’s check.

06_FullwithBrowserCache
That’s great. Files were not downloaded again. For browser’s request, server returns 304 & so browser has used its cache.  Thus it takes nearly 1 second only for further pages. We are fast now.

But wait, why the browser connects & requests the server for each file on each page load? It is an overhead for both the browser & server. How to force the browser not to check with server for any update & just use its cache?  The solution is, we can set an expiry time of a file from server, so that browser will use that file directly from cache & not disturb the server.

To set expiry details in header, in IIS manager:
We can set cache control by seconds or provide an exact expiry date.

07_Cache_IIS

Now going to our browser & check by refresh.

07_FullwithBrowser_ServerCache1
On first load, we can see the page downloaded with headers for cache added.

Let’s check how cache works by navigating the same page again:

07_FullwithBrowser_ServerCache3

0 Seconds!!! No download or request from browser to server, but the entire content from cache.
Let’s appreciate our self & also make sure to apply needed optimization in future development.

Further few points to optimize for CSS/JS:
- Link all CSS files first, before JS files.
- Request static content files from a cookie-less domain
- If a piece of CSS/JS code for a particular page & no need of caching, better use inline code of the page.
- Partition JS into two files. Need to render at startup should be included in header & other JS after page loaded or load asynchronous.

No comments: