In our past installments on Web performance optimization, we’ve seen how caching, server configuration, and the use of Content Delivery Networks (CDNs) can increase a Web site’s responsiveness and improve Web performance metrics. Most of the techniques we’ve reviewed have focused on configuring the Web server or optimizing server applications. Unfortunately, a Web page that downloads quickly but is slow to parse or execute on the client will appear just as slow to a user as if the Web server were on its last megabyte of memory. In this article, we’ll discuss some ways that Web page content can be streamlined for an optimal client-side experience.
Streamline JavaScript Includes
JavaScript abounds on the Web. From jQuery to Dojo, the Web is full of JavaScript libraries that can easily be dropped into a Web application. And any site whose developers are actively adding features is going to accrue its own storehouse of .js files. Unless a site’s JavaScript is carefully managed, its Web pages could end up making a dozen or more separate requests for scripts. As we’ve already discussed in our article on
web performance optimization non-caching strategies, the more requests your site makes, the slower it will load.
Tip of the hat to TechAttitude.com for the graphic showing how Web page sizes and number of objects have grown tremendously over the past 16 years. In the interesting article they state, “…the average size of a web page has increased by more than five times since 2003” and “the use of mulitmedia is increasing by 100% each year”.
Follow these guidelines to manage and reduce the burden of JavaScript on your Web pages.
- Use Minify to combine script files. As discussed previously, Minify will compile all of your disparate JavaScript files safely into a single .js file. This can collapse the number of HTTP requests made by a page from a half-dozen or more down to one single request.
- Remove unnecessary or expensive includes. JavaScript files whose functionality is no longer used should be stripped out. Site owners should also consider removing functionality that causes a script to load and execute multiple times on a page (e.g., a social media script that forces a script fetch for every individual post in a blog scroll).
- Consider a JavaScript compressor. If your site is loaded with client-side code, it may be worthwhile to use one of the many freely available JavaScript compressors on the market to shrink down your files. JavaScript Compressors remove extraneous whitespace, strip out comments, and shorten variable names. This means that JavaScript files not only faster to download, but faster to interpret and execute. A good JavaScript compressor is ShrinkSafe, which is also built into the dojo JavaScript toolkit.
Performance Tune Your JavaScript
Of course, optimizing JavaScript includes won’t help much if the code you use is inefficient. Poorly written or maintained JavaScript can harm browser performance in a number of ways. Consider:
- Closures. Closures are the most common cause of memory leaks in JS. A closure is a powerful mechanism that allows functions to be treated as first-class objects by retaining their execution context. Often, hard to spot circular references between a closure and one of its scoped variables causes the closure to remain in memory indefinitely. While the performance impact may be negligible at first, it builds quickly over time, until the user’s browser is running so poorly that she has no choice but to restart it.
- Circular references. Two objects that hold references to one another will never be garbage collected by the JavaScript run-time engine, resulting in even more leaked memory.
- DOM interactions. JavaScript is at its slowest when interacting with the Document Object Model (DOM).
Developers can surmount these problems using certain tools and techniques:
- Performance test JavaScript code. Performance testing can be as simple as using timestamps to measure the execution time of a particular segment of code. Developers who require a more detailed analysis of their code may opt to use a performance testing package such as jsPerf or jsLitmus.
- Avoid using expando properties. Another common source of memory leaks. As Gregory Baker and Erik Arvidsson note in their article on JavaScript performance, “You can use expando properties without introducing memory leaks, but it is pretty easy to introduce one by accident.”
- Avoid closures whenever possible. The IE team has provided an in-depth explanation of why developers should avoid closures except when absolutely necessary.
The book Speed Up Your Site: Web Site Optimization goes into even greater detail on subjects such as minimizing DOM interaction, selecting efficient algorithms, and improving loop execution.
Another in-depth resource that I recommend you explore is JavaScript Performance Rocks! by Amy Hoy & Thomas Fuchs. It’s a bundle of PDF books, demos, and a DOM Monster profiling tool for $39.
Remove Unnecessary or Expensive HTML
Finally, developers can squeeze even more performance out of their downloads and page rendering by cleaning up extraneous markup in HTML documents. This includes, but is not limited to:
- Reducing the use of DOM elements, such as unnecessary DIV and SPAN elements. These are expensive to create and maintain, and can cause memory bloat over the long term.
- Remove unnecessary IFRAME elements.
- Remove any IMG or IFRAME tags with a blank
src
attribute. These cause an additional request to be sent to the server. - Remove extraneous comments. They increase download time, and are stripped out by the parser anyway.
- Keep META tags and META content to a minimum. Other than the Description tag, most of the META elements no longer have any value for SEO.
Conclusion
The greatest factors in Web site performance are the number of requests between the client and the server and the speed of the individual requests. It is best to address these issues first through caching, tuning the Web application (database interactions), and Web server configuration before tackling HTML optimization. Development teams and Web site operators who have already addressed these issues can then optimize their client-side code to ensure that their pages load and execute efficiently once they are delivered to the client.