This chapter covers
As the old saying goes, “A picture is worth a thousand words.” Most websites today rely heavily on images to enhance their visual look and feel, so it isn’t surprising to learn that images often make up the bulk of a web page. Every byte counts in performance optimization and it’s important to optimize these images as much as possible.
In this chapter you’re going to learn about techniques you can apply to your website’s images that will reduce their file size and reduce the overall weight of your web pages. Modern image optimization techniques are proven to reduce image size by stripping unnecessary data from the file, thus reducing the file size without affecting image quality. The images on your website will look exactly the same but will be significantly lighter and quicker to download. You will learn how to use online and command line image optimization tools that will make a big difference to the size of your web pages. In this chapter, you will also discover data URIs and how they can be used with images in order to reduce the number of HTTP requests that a web page makes.
Images are a huge part of the internet today. Whether your website is a glossy e-commerce site, a magazine website, or a small blog, you will have made use of images at some point. Using images on your website can add and enhance the design, but they may add unnecessary bytes depending on the size and quality of the images. As you can see in figure 7.1, if you break down the components of the average website, you’ll find the bulk of the bytes come from the images.
The chart in figure 7.1, produced by httparchive.org and used with permission, shows the average number of bytes per content type on web pages. You can see that the images on an average web page make up a large portion of the overall bytes. In this case, this is almost 63%! Remember that even if you make big gains and reduce the size of scripts, styles, and HTML in a web page, the largest component may be the images. The easiest way to improve page performance, without removing any features, is to optimize the images. You don’t want to waste all the optimization work you’ve done thus far by including bloated images in your website. Leading up to this chapter, you’ve focused your optimization efforts on techniques such as compression, HTTP caching, minifying and bundling, and HTML optimization. But there’s been no direct emphasis on images as of yet. In chapter 3, you learned that compression is highly effective for removing extra bytes in a web page, but it can’t be applied to images because they’re already compressed.
If images are already compressed, how do you go about reducing the size of the files? Well, there are a few techniques you’re going to cover in this chapter that will help you reduce the size of your image files significantly.
I know that whenever I display images on a web page, I like to ensure that the image quality and clarity are as high as possible. Modern mobile phones, tablets, and computer screens are moving toward ultrahigh resolution screens that are capable of showing images at their best. The last thing you want to do is let image quality suffer when you reduce the size of an image. If you work in an organization with UI or graphic designers, they won’t be pleased with you if they find out their images have lost quality and become pixelated! Fortunately there are free tools available that optimize images without changing their look or visual quality. This is known as lossless optimization, and it ensures that the quality of the image will not degrade.
There’s visually no difference between the images in figure 7.2. The file size has been reduced, but the quality hasn’t changed during the optimization process. Although 35 KB is only a small savings, every file size reduction you make to the images on your web page means the overall page weight will begin to improve. Now I’m going to describe some of those free tools you can use to optimize and reduce the file size of your images. These are just a few of the tools that are available on the internet, so look for the tool that best suits your needs.
Smush.it is my favorite image optimization tool by far. It’s an online tool built by the team at Yahoo!, and is freely available at http://www.smushit.com/ysmush.it/. The tool is easy to use. You simply choose the files you wish to optimize and upload them to the smush.it website. Once optimization is complete, the tool will finish running and allow you to download the optimized images. The site also shows you the total file savings you’ll gain with all the images that you uploaded.
Smush.it will take most image formats (JPG, JPEG, PNG, and GIF) and process them for you. You’re going to work with the images in the Surf Store application later in the chapter so you can use the tool and see how effective it is at file optimization. Figure 7.3 shows the results from processing some image files with Smush.it, allowing you to compare your original file sizes to the optimized file sizes.
As you can see, you managed to cut 143.07 KB from the images—this is a significant chunk of data! All unnecessary metadata was stripped from the files without changing or otherwise affecting the quality of the images.
Another freely available online image optimization tool is Kraken. Available at http://kraken.io/, this tool is similar to Yahoo! Smush.it and offers support for all major image formats.
The site offers plugins for both Firefox and Chrome that allow you to optimize all the images on a web page. This tool is definitely worth considering.
Using a manual tool such as Smush.it requires a lot of human intervention, and depending on the frequency of your website updates, it may not always be the best option. But there are a few command line tools you can use to automate the image optimization process.
The one downside to using command line tools is each tool is aimed at a specific image format. Therefore you’ll need to run a different tool for each image format you work with. If done correctly, this can be achieved easily and integrated into your build or continuous integration process, which means the image optimization process becomes totally automated.
Pngcrush is a free image optimizer for PNG images. This image format is common on the web today, and all modern browsers support it. Pngcrush is available at http://pmt.sourceforge.NET/pngcrush/. Once you’ve downloaded the tool, simply fire up your command line in Windows and use the syntax in figure 7.4.
I’ve added a test image called original.png to the same directory as Pngcrush.exe. If you break this command line down, the key details are:
Once the tool has finished running, you’ll have a new file in the same folder called result.png. Depending on the contents and make-up of the image, the overall file size should be significantly reduced. Unfortunately, this tool is only for PNG format files and you’ll need to run other tools to process other image file formats.
A great tool that’s free and easy to use in a command line is Jpegtran. It can be run against the JPEG format and the command line setup is pretty similar to Pngcrush. To download the tool, visit http://jpegclub.org/jpegtran/. The site seems a little basic, but the tool works well and is efficient as a command line image optimizer for JPEGs.
Once you’ve downloaded the tool, fire up your command line in Windows. The syntax in figure 7.5 will process an image with the Jpegtran tool.
I’ve added a test image called original.jpg to the same directory as jpegtran.exe. If you break this command line down, the key details are:
You’ll notice that the command line and processing are quite similar to Pngcrush and figure 7.4. Once the tool has finished running, it will create an optimized file in the same directory as the tool.
Another great tool that’s available as a Visual Studio plugin is Image Optimizer. Unlike the image optimization tools we’ve already covered in this chapter, it’s an extension you can use from within the Visual Studio development environment. The extension adds a right-click context menu to any folder and image in your Solution Explorer and it allows you to automatically optimize all PNG, GIF, and JPEG files in that folder. The extension uses the Yahoo! Smush.it and PunyPNG tool to optimize the images. To download the extension, go to http://mng.bz/2MR6.
Figure 7.6 shows the right-click context menu that’s available with the Image Optimizer extension. Once you download and install the extension, right-click a folder or individual image and select Optimize. The image(s) will be optimized automatically and you won’t even need to leave Visual Studio.
While this tool is handy and enables you to optimize your images at the click of a button, you might find automating the updates using a command line tool is more effective depending on your environment setup and how often you change your images.
So far you’ve learned about many of the tools you need in order to optimize your images and reduce their overall size. This reduction can go a long way toward reducing the total weight of your web pages, but what if there was a way to show these images without even making an HTTP request for them? It doesn’t sound possible, but there is a sneaky trick you can apply using data URIs.
Data URIs are a scheme modern browsers use to read image objects that are embedded in a web page. Embedding data means the browser doesn’t need to make an extra HTTP request to retrieve the image. The data URI scheme provides a way to include data in-line in web pages, as if they were external resources. You can actually embed the image in the page without having to make a request to the server! Instead of adding a reference to your image as a path or URL, you embed the image directly into the document using a Base64-encoded string. The data URI scheme can be applied to images in CSS, link tags, and image tags. The browser automatically understands the string and decodes it there and then instead of retrieving it via an HTTP request.
Normally you would reference an image in your HTML like so:
<img alt="Windows 8 Logo" src="/images/windows_logo.png" />
If you used data URIs, it would look something like this:
<img alt="Windows 8 Logo" src="data:image/png;base64, /9jAAQSkZJRg==)" />
The difference is the image can be decoded from the same page, meaning one less HTTP request and a faster page load time. In the sample that’s provided, the data string is quite short, but you’ll notice a much longer string if you’re using a larger image.
You can achieve the same effect by using data URIs in CSS. You normally reference an image like this:
.logo { background: url("/content/images/logo.png") }
But you can reference the image like this with data URIs:
.logo { background: url(data:image/gif;base64,R0lGODlhEAAQATWGVQ887AG) }
Data URIs are a great way to reduce the overall page weight and the number of HTTP requests your web page is making. If your website focuses on mobile device usage, the fewer HTTP requests your website needs to make, the better the performance.
The advantages of using data URIs are:
Unfortunately, data URIs aren’t without their limitations. As a rule, you should only use the data URI scheme when your images aren’t too large. A large image will create a very long string in your HTML, and your string size might become significantly larger than the original image size! Other disadvantages of using data URIs are:
As with most new features, some older browsers don’t offer support, but it isn’t as bad as you think—Firefox, Chrome, Opera, Safari, and IE8+ all offer support for data URIs. Another factor to consider is that you need to update the data URI every time you make a change to an image. This could become a maintenance nightmare if your website is image-intensive. The best way to handle this is to automate the data URI creation process. This is where ASP.NET comes in. You’re about to learn about a technique that will enable you to apply automatic encoding logic to your images so you don’t have to re-encode each time you update your image!
If you decide to use data URIs on your website, you should still try to optimize your images using the image optimization tools mentioned earlier. Reducing the image file sizes will also mean that you’ll produce smaller Base64-encoded strings.
You may be wondering whether it’s worth going to all this effort to produce data URIs automatically. You need to choose the code that applies to your situation best. If you find your images, icons, or logos don’t change that often, you might be better off generating the data URI manually, but you won’t get the benefit of browser detection logic. With a bit of clever caching, this code can produce lightning fast results and shave precious milliseconds from your page load time.
HTML helpers in ASP.NET MVC can be a great way to quickly and easily apply repetitive server-side logic to operations on your Views. We’re going to cover an example that will get you comfortable using the data URI scheme on your images in no time. The updates are going to be applied to the source code of the Surf Store application.
As the web developer for the Surf Store website, you’ve decided it needs a logo in the header bar. This is a great opportunity to use data URIs because the image is small and the technique will require one less HTTP request to the server. The HTML code in the Layout view has been updated to include a small logo, as shown in figure 7.7.
How do you make this update? Begin by navigating to your Solution Explorer and adding a class file called DataUriUtils.cs to the Utils folder (figure 7.8).
Inside the DataUriUtils.cs class file, add this code.
The code is used to determine if the user’s browser is capable of handling data URIs. Earlier versions of IE aren’t capable of handling data URIs. In order to serve the same experience to all users regardless of their browser, it’s best if you check first. You want users with an older browser to see the images.
Next you need to perform a check to see if the file size is within a suitable boundary. Add the following code to the same class in your solution.
The code checks to see if the file size is less than 32 KB, and returns a Boolean value you’ll use to decide whether to proceed with the optimization. If it returns true, then it will proceed and return a data URI image. If it is false, it will simply fall back and return the original image.
Now you need to convert the image to a Base64-encoded string. The code in the following listing uses the image URL and creates a Base64-encoded string based on the image that it reads.
Combining all the methods will return a chunk of image HTML and will be embedded in the page using the HTML Helper. You can use HTML Helpers to reduce the amount of tedious typing you must perform to create a standard HTML page.
The code in listing 7.4 uses the methods you’ve worked on and combines them to create your image HTML using data URIs. First, you use the two methods that you wrote in listings 7.1 and 7.2. This code checks if the file size isn’t too large and also that the browser is capable of handling data URIs. You need to do this in order to serve the best experience to all users regardless of the browser that they are using. If the image passes the first two checks, the code converts the image to a Base-64 encoded string and builds an image tag with the data URI scheme and the Base-64 encoded string. If for any reason the image didn’t meet the criteria, it will be returned as a standard image tag.
You now need to implement the code on your views. You’re adding this change on the Layout view because it’s being used for the standard layout for the logo across all views. Instead of creating a standard HTML image tag, you’re going to use the HTML Helper that you created. The code in the next listing will create an HTML image tag if the image and the browser meet the requirements.
If you fire up the application and review the results of the HTML, it will look something like this:
<div class="span3"> <!-- Logo --> <a href="/" class="logo_bar"> <img alt="Surf Store Logo" src="data:image/png;base64,iVBORw0KGgo AAAANSUhEUgAAACg AAAAoCAYAAACM/A9 Zoyj8pW/wfGAx77w dBG5WoOXAAAAAASU VORK5CYII=" /> Surf Store Application</a> </div>
By using this HTML helper to produce a data URI in the HTML, you’ve effectively created one less request for the browser.
If you compare the logo in the Surf Store application before and after applying the data URIs, you’ll notice there is no visual difference whatsoever. The browser has interpreted the Base64-encoded string and converted it to the logo in figure 7.9.
Using the power of the ASP.NET framework, data URIs can be easily implemented into a Web Forms application. The first thing you need to do is check to see if the user’s browser is compatible with data URIs. Using ASP.NET, you can easily check the browser’s capabilities and apply this logic on the server side, but it would be best if you had a method that simply produced the HTML you need and did the check at the same time.
In this example, you’re going to make changes to the Surf Store application’s source code. As the web developer on the site, you’ve decided it needs a logo in the header bar. This is a great opportunity to use data URIs because the image is small and this technique will require one less HTTP request to the server. The HTML code in the Master page has been updated to include a small logo, as shown in figure 7.10.
Next, navigate to your Solution Explorer and add a class file called DataUriUtils to the Utils folder (figure 7.11).
Inside the DataUriUtils.cs class file add the code in listing 7.6.
The code determines if the user’s browser is capable of handling data URIs. Internet Explorer 8+ is capable of handling data URIs. You still want to serve the same experience to all users regardless of their browser, so it’s best if you check first. You don’t want some users on an older browser not to see the images! If the code detects an older browser, you return a standard image instead.
Next you need to check to see if the file size is within a suitable boundary. Add the following code to the same class in your solution.
The code checks to see if the file size is less than 32 KB, and returns a Boolean value that you’ll use to decide whether to proceed with the optimization.
Next, you need to convert the image to a Base64-encoded string. The code in the following listing uses the image URL and creates a Base64-encoded string based on the image that it reads.
Finally, you wrap it all up. You can use all of the previous methods together to return a chunk of image HTML.
The code in the listing uses the methods that you’ve worked on and combines them all to create your image HTML using data URIs. In order to serve the best experience to all browsers, the code checks if the file size isn’t too large and if the browser is capable of handling data URIs. If the image passes the first two checks, the code then converts the image to a Base64-encoded string and builds an image tag using the data URI scheme and the Base64-encoded string. If for any reason the image did not meet the criteria, it will get returned as a standard image tag.
Now you need to implement this code in your web pages. I am adding this change on the Master page because it’s being used as a standard layout for the logo across all pages. Instead of creating a standard HTML image tag, I am going to use static method that you created.
The code in listing 7.10 will create an HTML image tag if the image and the browser meet the requirements. If you fire up the application and review the results of the HTML, it will look something like this HTML:
<div class="span3"> <!-- Logo --> <a href="/" class="logo_bar"> <img alt="Surf Store Logo" src="data:image/png;base64,iVBORw0KGgo AAAANSUhEUgAAACg AAAAoCAYAAACM/A9 Zoyj8pW/wfGAx77w dBG5WoOXAAAAAASU VORK5CYII=" /> Surf Store Application</a> </div>
By using this HTML helper to produce a data URI within the HTML, you’ve effectively created one less request for the browser. Because the image is small enough, it hasn’t had an impact on the overall size of the HTML.
When you compare the logo in the Surf Store application before and after applying the data URIs, you’ll notice there is no visual difference. The browser has interpreted the Base64-encoded string and has converted it to the logo in figure 7.12.
After you’ve processed and optimized the images in your web pages, look out for image dimensions in your HTML. It’s easy to forget to specify the height and width of an image on your web page.
<img src="/Content/Images/image.jpg" />
The preceding code snippet is an example of an HTML image tag without the dimensions specified. It’s important to specify the dimensions of an image because if a browser knows the dimensions of an element in a web page, it can begin rendering even before the images are downloaded. As the page is parsed and the browser begins laying it out, it needs to be able to flow around elements such as images. You’ll even notice this appears as a suggestion when you profile your site using Google PageSpeed. Figure 7.13 shows the Google PageSpeed suggestion to specify image dimensions.
If dimensions aren’t specified on the image tag, the browser will need to reflow and repaint once the image is downloaded. It’s best if you specify your images similar to this code snippet:
<img src="/Content/Images/image.jpg" width="120" height="120" />
This simple change will allow the browser to render your page faster and begin displaying images and content to your users even before all the images are downloaded.
Using the Surf Store application you’ve worked with throughout this book, you optimized and reduced the file size of the images using free tools that are available to download online. Next, you added a small logo to the Surf Store application and using data URIs you reduced any extra HTTP requests that needed to be made.
Now that you’ve made your improvements to the Surf Store application, you can compare the applications before and after performance. In this previous chapter, you looked into the advantages of using HTML5 in a web application. These advantages reduced the size of the HTML and after running the Surf Store application through the Google PageSpeed tool, the score on the home landing page came in at 91. Using the Yahoo! YSlow tool, the empty cache for the landing page showed 11 HTTP requests and a total page weight of 835 KB.
In this chapter, the total weight of the images on the landing page came to around 686 KB and 6 images in total. If you compare the changes after the image updates you’ve made in this chapter, the results are impressive (figure 7.14).
Wow! The overall PageSpeed score has jumped from 91 to 99 (out of 100). You’ve managed to make some pretty significant improvements to the overall load time and page speed. If you take a look at the Yahoo! YSlow results after making these changes, the results reveal similar gains (figure 7.15).
The Yahoo! YSlow performance score has also jumped up to 94, which is a significant improvement from 91. This is a solid result and you’ve significantly improved the performance score since you started out in chapter 3.
The chart in figure 7.16 shows that the overall image weight has also been reduced.
By applying the image optimization techniques you learned in this chapter, you’ve managed to cut about 147 KB from the image weight and therefore the total weight of the page. This is a significant reduction. If you applied these techniques to any site you’re currently working on, you could produce even larger savings.
Images are often the heaviest components by weight in most web pages. By optimizing the images in your web pages, you can significantly reduce their size and reduce total page weight. In this chapter, you learned about freely available tools you can use to optimize your images and reduce their file size.
The image optimization tools you learned about in this chapter use lossless optimization, which won’t affect the look or visual appearance of the images in any way. You learned about two online tools: Smush.it by Yahoo! and Kraken.io which allow you to optimize your images online and in batches. Another alternative is the ability to automate image optimization. Two tools you looked at were Jpegtran and Pngcrush—both are command line-based and are very effective at optimizing images. The final tool you learned about was the Image Optimizer for Visual Studio. It allows you to automate image optimization inside of Visual Studio with the click of a button.
Data URIs can be manually added to a web page, but in this chapter you learned a technique that allowed you to convert the image to a Base64-encoded string and embed the resource in the page automatically. The technique handles images that are updated frequently and makes sure you don’t need to update your HTML each time the change takes place. The code takes support for older browsers into account, as well as images that might be too large.
This chapter was an important step in the overall performance improvement of your website. Optimizing the images in your website can save valuable bytes and improve your page load times radically. Even though you’ve produced great Google PageSpeed and Yahoo! YSlow performance scores thus far, you can take your website even further and produce better results! In the next chapter, you’ll learn more about ETags and why they’re important to web page performance.
3.144.114.223