Article
Cost-Effective Website Acceleration
JavaScript Optimization
More and more sites rely on JavaScript to provide navigational menus, form validation, and a variety of other useful things. Not surprisingly, much of this code is quite bulky and begs for optimization. Many of the techniques for JavaScript optimization are similar to those used for markup and CSS. However, JavaScript optimization must be performed far more carefully because, if it's done improperly, the result is not just a visual distortion, but potentially a broken page! Let's start with the most obvious and easiest improvements, then move on to those that require greater care.
11. Remove JavaScript comments.
Except for the <!-- //--> masking comment, all JavaScript comments indicated by // or /* */ can safely be removed, as they offer no value to end users (except those who want to understand how your script works).
12. Remove white space in JavaScript.
Interestingly, white space removal in JavaScript is not nearly as beneficial as it might seem. On the one hand, code like this:
x = x + 1;
can obviously be reduced to:
x=x+1;
However, because of the common sloppy coding practice of JavaScript developers failing to terminate lines with semi-colons, white space reduction can cause problems. For example, consider the legal JavaScript below, which uses implied semi-colons:
x=x+1
y=y+1
A simple white space remover might produce the following:
x=x+1y=y+1
This would obviously throw an error. If you add the needed semi-colons to produce:
x=x+1;y=y+1;
you actually gain nothing in byte count. We still encourage this transformation, however, since Web developers who provided feedback on the Beta versions of w3compiler found the "visually compressed" script more satisfying (perhaps as visual confirmation that they are looking at transformed rather than original code). The also liked the side benefit of delivering more obfuscated code.
13. Perform code optimizations.
Simple ideas like removing implied semi-colons, var statements in certain cases, or empty return statements, can help to further reduce some script code. Shorthand can also be employed in a number of situations. For example:
x=x+1;
can become:
x++;
However, be careful, as it's quite easy to break your code unless your optimizations are very conservative.
14. Rename user-defined variables and function names.
For good readability, any script should use variables like sumTotal instead of s.
However, for download speed, the lengthy variable sumTotal is a liability and it provides no user value, so s is a much better choice. Here, again, writing your source code in a readable fashion and then using a tool to prepare it for delivery shows its value, since remapping all user-defined variable and function names to short one- and two-letter identifiers can produce significant savings.
15. Remap built-in objects.
The bulkiness of JavaScript code, beyond long user variable names, comes from the use of built-in objects like Window, Document, Navigator and so on. For example, consider this code:
alert(window.navigator.appName);
alert(window.navigator.appVersion);
alert(window.navigator.userAgent);
You could rewrite the above as follows:
w=window;n=w.navigator;a=alert;
a(n.appName);
a(n.appVersion);
a(n.userAgent);
This type of remapping is quite valuable when objects are used repeatedly, which they generally are. Note, however, that if the window or navigator object were used only once, these substitutions would actually make the code bigger, so be careful if you are optimizing by hand. Fortunately, many JavaScript code optimizers will take this into account automatically.
This tip brings up a related issue regarding the performance of scripts with remapped objects: in addition to the benefit of size reduction, such remappings actually slightly improve script execution times because the objects are copied higher up into JavaScript's scope chain. This technique has been used for years by developers who write JavaScript games, and while it can improve both download and execution performance, it does so at the expense of local browser memory usage.
The Obfuscation Side Effect of JavaScript Optimization
You'll notice that, if you apply these various JavaScript optimizations, the source code becomes effectively unreadable or, some might even say, obfuscated. While it's true that the reverse engineering of optimized JavaScript can be difficult, it is far from impossible. Real obfuscation would use variables like O1l1l1O0l1 and Ol11l001l, so that unraveling the code would be more confusing. Some may even go so far as to employ light encryption on the page. However, be aware that, in general, obfuscation and optimization can be at odds with each other, to the point that more obfuscated code may be larger than the original code. Fortunately, lightweight code obfuscation is generally enough to deter casual code thieves, while still offering performance improvements.
File-Related Optimization
The last set of optimization techniques is related to file and site organization. Some of the optimizations mentioned here might require server modifications or site restructuring.
16. Rename non-user accessed dependent files and directories.
Sites will often have file names such as SubHeaderAbout.gif or rollover.js for dependent objects that are never accessed by a user via the URL. Very often, these are kept in a standard directory like /images, so you may see markup like this:
<img src="/images/SubHeaderAbout.gif">
Or, worse:
<img src="../../../images/SubHeaderAbout.gif">
Given that these files will never be accessed directly, this readability provides no value to the user, only the developer. For delivery's sake it would make more sense to use markup like
<img src="/0/a.gif">
While manual file-and-directory remapping can be an intensive process, some content management systems can deploy content to target names, including shortened values.
Furthermore, the w3compiler has a feature that automatically copies and sets up these dependencies. If used properly, this can result in very noticeable savings in the (X)HTML files that reference these objects, and can also make reworking of stolen site markup much more difficult.
17. Shorten all page URLs using a URL rewriter.
Notice that the previous step does not suggest renaming the host files like products.html, which would change markup like this:
<a href="products.html">Products</a>
to something like this:
<a href="p.html">Products</a>
The main reason is that end users will see a URL like http://www.sitename.com/p.html, rather than the infinitely more usable http://www.sitename.com/products.html.
However, it is possible to reap the benefits of file name reduction in your source code without sacrificing meaningful page URLs if you combine the renaming technique with a change to your Web server's configuration. For example, you could substitute p.html for products.html in your source code, but then set up a URL rewriting rule to be used by a server filter like mod_rewrite to expand the URL back into a user friendly value. Note that this trick will only put the new URL in the user's address bar if the rewrite rule employs an "external" redirect, thereby forcing the browser to re-request the page. In this case, the files themselves are not renamed, as the short identifiers are only used in the source code URLs.
Because of the reliance on URL rewriting and the lack of widespread developer access to, and understanding of, such server-side tools as mod_rewrite, even an advanced tool like the w3compiler does not currently promote this technique. However, considering that sites like Yahoo! actively employ this technique for significant savings, it should not be ignored, as it does produce noticeable (X)HTML reduction when extremely descriptive directory and file names are used in a site.
18. Remove or reduce file extensions.
Interestingly, there really is little value to including file extensions such as .gif, .jpg, .js, and so on. The browser does not rely on these values to render a page; rather it uses the MIME type header in the response. Knowing this, we might take:
<img src="images/SubHeaderAbout.gif">
and shorten it to:
<img src="images/SubHeaderAbout">
If combined with file renaming, this might produce:
<img src="/0/sA">
Don't be scared by how strange this technique looks; your actual file will still be sA.gif. It's just the end user who won't see it that way!
In order to take advantage of this more advanced technique, however, you do need to make modifications to your server. The main thing you will have to do is to enable something called "content negotiation," which may be native to your server or require an extension such as mod_negotation for Apache or Port80's pageXchanger for IIS. The downside to this is that it may cause a slight performance hit on your server.
However, the benefits of adding content negotiation far outweigh the costs. Clean URLs improve both security and portability of your sites, and even allow for adaptive content delivery whereby you can send different image types or languages to users based upon their browser's capabilities or system preferences! See "Towards Next Generation URLs" by the same authors for more information.
Note: Extension-less URLs will not hurt your search engine ranking. Port80 Software, as well as major sites like the W3C, use this technique and have suffered no ill effects.
19. Restructure <script> and <style> inclusions for optimal number of requests.
You will often find in the <head> of an HTML document markup such as:
<script src="/scripts/rollovers.js"></script>
<script src="/scripts/validation.js"></script>
<script src="/scripts/tracking.js"></script>
In most cases, this should have been reduced to:
<script src="/0/g.js"></script>
Here, g.js contains all the globally used functions. While the break-up of the script files into three pieces makes sense for maintainability, for delivery, it does not. The single script download is far more efficient than three separate requests, and it even reduces the amount of needed markup. Interestingly, this approach mimics the concept of linking in a traditional programming language compiler.
20. Consider cacheability at the code level.
One of the most important improvements to site performance that can be made is to improve cacheability. Web developers may be very familiar with using the <meta> tag to set cache control, but (apart from the fact that meta has no effect on proxy caches) the true value of cacheability is in found in its application to dependent objects such as images and scripts.
To prepare your site for improved caching, you should consider segmenting your dependent objects according to frequency of change, storing your more cacheable items in a directory like /cache or /images/cache. Once you start organizing your site this way, it will be very easy to add cache control rules that will make your site clearly "pop" for users who are frequent visitors.
Conclusion
You now have twenty useful code optimization tips to make your site faster. One by one, they may not seem very powerful, but, apply them together, and you'll see an obvious improvement in site delivery.
In the next installment of this series, we'll focus primarily on caching, explaining how it is generally misused and how you can significantly improve performance with just a few simple changes. See you then!