Performance optimization has been more than ever in the spotlight of web developers, especially for mobile web developers who have to understand and know by heart the challenges and constraints of mobile devices: these devices run off a battery that e.g. drains faster if performance is not taken seriously. The devices are powered by smaller CPUs than desktop devices. Unknown factors like latency and network connectivity challenge developers to build slim, light-weight and fast websites. Data plans still remain expensive and inconsiderate use of served data by web developers should not be ignored.
Clearly, performance is (and should) not (be) an after-thought anymore. When web developers create websites, performance can influence the success or failure of a web product. We’ve been hearing from leading performance advocates like Ilya Grigorik that speed is a feature and should not only be thought of just before a product hits production but rather as an essential part of the web product development cycle.
In today’s blog post I will be sharing some of the plugins for Grunt that can be used to speed up and automate performance optimization. At the end of the blog post, I will present performance results that will show that frontend optimization (FEO) can be fun and easily be automated to cut page load time.
Note: The post assumes that you’ve worked with Grunt before and know how it’s been installed, and how to install plugins (I won’t go into details, however links at the bottom will help you)
“Let’s grunt it up”
(All plugin headings in this post are clickable links to their appropriate pages)
Montage helps you sprite images to reduce HTTP requests. You will need ImageMagick to be installed. Alternatively, you can also try out grunt-spritefiles.
<!-- build:js js/magic.min.js --> <script src="js/1.js"></script> <script src="js/2.js"></script> <script src="js/3.js"></script> <script src="js/4.js"></script> <!-- endbuild -->
You can use grunt-processhtml instead.
Same logic and idea than uglify, once your CSS files are all concatenated, use cssmin to shrink several lines of CSS code into one single one.
imagemin minifies JPG and PNG images. It’s a handy Grunt plugin if you don’t know if the assets you got handed from your designer (or yourself) are optimized for web yet. By using this tool, you have the piece of mind that you use image files in an efficient way. Alternatively, you could use grunt-smushit, it’s based on Yahoo’s great smushit tool that is available in the YSlow plugin for several browsers.
This plugin encodes images as base64 and leverages the technique of data URIs for images, something that can be used inline with CSS to reduce HTTP requests and hence reduce page load time. I’ve written a blog post where this is explained in more detail.
Use grunt-exec to run the SPOFcheck. An excellent tool to identify bad 3rd party scripts includes, developed by the eBay team. I didn’t include the scripts asynchronously, hence SPOFcheck complaints to avoid SPOF.
“It’s Magic” Sample Page
I created a simple page themed “It’s magic” where I applied all mentioned plugins. You can find the files including Gruntfile.js here. Please note, I intentionally didn’t put a lot of effort into the styling (It is supposed to look as simple and cheesy as it feels to you)
This file is the one that Grunt will create for you. Visually, the file doesn’t look that different, besides the fact that the title has changed….see yourself
Below are screenshots of the two pages (and links) side by side, the one on the left before Grunt tasks were applied. The right one shows the page after Grunt tasks were applied. For the user they both look the same (except for the heading).
Can you spot the differences?
- The logo was being transformed into a data URI
- The title has changed from It’s not magic to It’s magic
- The HTML was being compressed, comments were taken out automatically
- The next and previous buttons were converted to a sprite file
- On build, SPOFcheck was applied and gave us the following warnings so we could address possible SPOF issues
Let’s take a look under the hood
Here are the waterfalls for both versions:
I ran WebpageTest for both files with 9 runs for IE8 with a DSL connection to retrieve the median. Here are the performance results:
- HTTP requests dropped by ~48%
- Page load time (PLT) dropped by ~10%
- File sizes dropped by ~10%
Even if those numbers are not that high (mostly due to the simplicity of the experiment), it shows that Grunt can help you automatically optimize your deployment process.
As you can tell by the sample code, there are many mix and match options available, depending on the magnitude and granularity of your page structure. Nevertheless, this little sample shows how to use Grunt to optimize performance and to illustrate what is possible. Feel free to use the code as a starting point, and tweak or customize it to your likings.
General references and info to get you started with Grunt
There is always room for improvement. Period.
Think about the 100 meter men’s sprint. I am amazed how it continues to be possible for human beings to still become faster and improve their performance.
I’m not Usain Bolt – I can’t run 100 meters in 9.58 seconds but I might be able to run (mobile) websites under 10 seconds.
Today, I want to focus on a technique I first heard about at the Velocity Conference in 2011 in Santa Clara and how to compare it with other ways to serve images in HTML pages.
Data URI is based on base64 encoding and basically encodes data (e.g. images) into bites. It can be used to improve performance.
Data URI as “Performance Enhancer”
Instead of requesting for example a PNG image, you could encode it as base64 and serve it inline with your HTML code. That way, you reduce one HTTP request – right there – 200ms saved. Instead putting it inline, you could also put it encoded in an external stylesheet.
Watch out for caching limitations though. Data URIs can’t be cached as they don’t have a standalone cache policy, they are part of the file that includes them. So they can only piggy-bag on other cacheable assets, e.g CSS or HTML files.
As Nicholas explains, if you put data URI images inline with HTML, they can only be cached as part of the HTML cache control header. If the HTML is not cached, the entire content of the HTML markup, including the inline data URI will be re-downloaded every single time. That approach, if the image is big in size, can slow down and weight down your page. Hence, one option is to to put it in stylesheets because they can have an aggressive cache while the HTML page can have no cache or a very limited cache.
Limitations and Browser Support
Think about the browser audience of the site you want to leverage data URIs for. If you target modern browsers, including new mobile devices because that’s where you really want to focus on performance the most, you might be able to ignore the following limitations and accept the little restricted list (thanks to Fire) of supported browsers.
- Firefox 2+
- Opera 7.2+ – data URIs must not be longer than 4100 characters
- Chrome (all versions)
- Safari (all versions)
- Internet Explorer 8+ (data URIs must be smaller than 32KB)
Motivation for Comparison
I’ve been reading a lot about web performance techniques and for some reason the data URI practice got stuck with me. I started off by creating the CBC gem (logo) in CSS to verify if CSS performs better than serving images. While I was playing around with that, I thought why not adding another dimension to the test and check the performance of the CBC logo as data URI. Voilà, I had my basic scenario for the test:
Check the performance of the CBC logo as
- An image in pure css
- A plain PNG image as background image
- A data URI (in CSS and inline with HTML)
Setting up the Test
The purpose of the test was to figure out what kind of presentation for the CBC gem would be the fastest and slimmest.
Prerequisites and Conditions
- All HTML and CSS files were minified and use the same markup (despite the logo in pure CSS which needed to have a few more div classes to render the circles)
- Each HTML version was tested with empty cache
- Performance results were performed with WebPagetest (10 runs on an 3G simulated browser) to find the Median.
1. Logo in pure CSS (30px x 30px)
|Description: Thankfully, the CBC gem consists of circles, 1/2 and 1/4 circles, those shapes can easily be created with CSS. I used this page to help me get started. Instead of setting up a fixed size and color, I decided to use SASS to help me be more flexible with my settings for the logo. The scss file lets me define color and size of the gem.
Note: Maybe the pure CSS logo has a bit of issues with some of the 1/4 circles but that’s probably due to some math formulas I didn’t do right in the SASS, I believe this can be ignored. Hence, This version cannot be used as the official CBC gem.
2. Plain PNG Image (30px x 30px)
|Description: Simple PNG file included in the CSS as a background image. CSS included in main HTML.|
3. Data URI in CSS (30px x 30px )
|Description: I used Nicholas’ tool to create my CSS files including data URI. However there are many tools to help you create your own data URI encoded files.|
You can see from the browser screenshots above that all logos look pretty much the same to the user.
The results show that the median load times serving the logo as pure CSS in comparison to the Data URI solution are being almost the same whereas the logo as a background image in CSS took the longest.
I looked at the base64 string and thought how big it would be if I had used a bigger image. So I googled and found the following “It’s not worth to use data URIs for large images. A large image has a very long data URI string (base64 encoded string) which can increase the size of CSS file.” (source). I decided to test it out myself. So, my next question was “How would the test above turn out if I used a bigger CBC gem logo”. I picked a width and height of 300px. While I was preparing the 300px x 300px pages, I also decided to create another version of the Data URI, not part of the CSS but inline within the HTML.
1. Logo in pure CSS (300px x 300px )
There was not much of a different in terms of markup and setup for the pure CSS and PNG in CSS version. I updated the SASS for the cbcgem.scss to accomodate a logo of 300px x 300px instead of 30px x 30px. The file size didn’t change much because it is all based on math calculations
2. Plain PNG Image (300px x 300px )
Instead of loading gem-30.png, I created a version gem-300.png and updated the CSS.
3a. Data URI in CSS (300px x 300px)
I noticed that the size of the Data URI encoding as expected increased dramatically from a 30px x 30px encoded image to a 300px x 300px image (almost 10 times, see full view of screenshot on the left).
3b. Data URI inline within HTML (300px x 300px)
I used WebPagetest again to run 10 tests to find the Median.
Observations & Take-Aways
- Creating simple shapes in CSS (via SASS) is highly scalable because it doesn’t influence the size of the CSS file significantly. The size of the CSS file won’t change much if I choose to produce a 300px x 300px logo or a 10px x 10px logo. For all tests performed this solution seems to be the most efficient and fastest one.
- I didn’t find the observation true that if the encoded image is bigger than 1-2kB it wouldn’t be worth using Data URI to improve performance. When looking at the last test round (300px x 300px), we can see in the results that the page with the encoded image is still faster than the page with a 300px x 300px PNG image.
- It is interesting to note that the inline data URI version is faster than the data URI CSS version (and almost as fast as the pure CSS version). Having to serve 2 HTTP requests with a total size of 4kB, the median load time was faster than the one serving the data URI via CSS.
Further Readings and References
- Data URIs explained (by Nicholas C. Zackas)
- Data URI Sprites
- Data URIs explained
- High Performance Web Apps. Use Data URIs. Theory
- High Performance Web Apps. Use Data URIs. Practice
CBC Gem 30px x 30px
- Pure CSS: http://www.webpagetest.org/result/130417_5Q_179
- PNG: http://www.webpagetest.org/result/130417_4S_181
- Data URI: http://www.webpagetest.org/result/130417_9S_16K
CBC Gem 300px x 300px
I love talking about, and listening to the things I am passionate about (who doesn’t?). I love sharing my knowledge and learning about others. I love conferences. It’s a great place to learn new things, validate your knowledge, connect with like-minded and come back home with a bunch of things you want to try out and work on.
So it happens that one of the things on “my list of things to do in life” is/was to present at a conference. I happily and proudly checked this off last weekend.
I had the pleasure to speak with a smart colleague at FITC’s “Web Performance and Optimization” conference in Toronto, this past weekend.
Our topic was similar to the one we submitted (and got accepted) to the O’Reilly’s Velocity conference in San Clara this summer. I’m so beyond excitement to be presenting similar things (and more) to all those great and talented web performance enthusiasts in a few months.
Allow me to give a brief recap of the presentation from last Saturday – the way I experienced it.
It was a small conference, around 70 people attending, probably ~7 of those attendees were women – that’s it, not more! Well, not a huge surprise to me, I’m used to that from my time as a Computer Science student 10 years ago. But is the ratio still so drastic? Oh, and in addition, I was the only female speaker that day.
While I was listening first (and later presenting myself), I noticed that most male presenters had a very specific way of selling and promoting themselves – They all were very confident (Not jealous, good for you, boys!). A supportive and beautiful person on my side that day, full of great constructive criticism, noted something after I was done presenting. She confirmed something that I had honestly (and secretly) already felt, she said I could have been more promoting myself “..like the guys did”. It’s true, as the only woman speaking that day, I could have represented the female minority better by maybe emphasizing my successful web performance results to those 63 men and 7 women that day. Well, it’s not that I wasn’t passionate about my topic – Maybe it’s just that women share their success in a different, less self-selling way and/or are less confident.
I’d like to quote something from Geek Feminism now:
So! Getting women to submit content: easy? Um. When I’d talk to men about the conference and ask if they felt like they had an idea to submit for a talk, they’d *always* start brainstorming on the spot. I’m not generalizing — every guy I talked to about speaking was able to come up with an idea, or multiple ideas, right away…and yet, overwhelmingly the women I talked to with the same pitch deferred with a, “well, but I’m not an expert on anything,” or “I wouldn’t know what to submit,” or “yes but I’m not a *lead* [title], so you should talk to my boss and see if he’d want to present.”
Ok! So I guess I am not imagining all of this. It really seems to be true that men are generally more confident than women when it comes to work related areas where they can promote themselves.
The beautiful thing about life is that you (can) always learn and get better.
And to be honest, my observation at FITC’s conference has even more encouraged me to submit call for speakers forms! I enjoyed presenting! Like a lot – You ain’t stoppin’ me now.
Below the slides from our talk on Saturday
Additional resources in regards to women in tech and female speakers
so i have been getting involved more and more in VS2005 lately. i have to say windows is surprising me and is actually making my life really easier when it comes to building web applications. today, i found out about a nice tool to manage displaying different content depending on their role. the role management offered by vs2005 is nice and can be used very easily. It allows me to customize information that will be presented by users through different templages. This is done based on theirs roles.
It’s sometimes recommended to read about the “what’s new”.
i seem to not be able to stop reading about the “new” web. while i am still trying to get news and information about web2.0 and being excited about this “WebOS” and the web becoming the main application platform for users these days, i have found another terminology today (maybe for a lot nothing new, for me something new to research): semantic web or …1…2…yeah web3.0
Tim Berners-Lee describes the idea in his semantic web road map article and says clearly that the problem is still that “the web is designed for human cunsumption” but “the structure of the data is not evident to a robot browsing the web“. So the idea of the semantic web clearly tries to “solve this problem by developing languages for expressing information in a machine processable form“.
if you need examples and maybe a bit “easier” article to read, the bbc article “Smart sites to power semantic web” might belp you.
seriously, i don’t know why some people decided to use coldfusion 4.5: right now, i have to understand and enhance somebody’s coldfusion code to make it work for the company i work for. while trying to do that, i realize that most of the functions that i need now to speed up the code, are not available for version 4.5
is there anybody who has a good resource for coldfusion 4.5?
moving forward to more futuristic methods/technologies:
i found a nice one-chapter example of the new series by o’reilly: head rush AJAX.
I really like the style how this serie of books presents its content to the readers: easy, funny and nice to read and understand. I am really thinking of buying it.
Another one I am reading/using is this one: head first design patterns.