Optimizing script loading

WordPress is using more and more JavaScript. A lot of features use AJAX and nearly all UI customizations and enhancements depend on it. In 2.7 there is some optimization for caching, especially when Turbo (Gears) is used all pages load in under 1 sec. However the cache control was left to the server and there seem to be a lot of servers with less than perfect settings for it.

There are many ways to optimize script loading in 2.8. Listing several of them roughly in order of ease of implementation/most effective:

  • Minify (but not “pack”) all js files. Although the file size is larger, minified js loads faster than “packed” js, as it takes the browser some time to “unpack” it. Here’s a nice post on the subject. In 2.8 we should replace all “packed” js with minified and also minify all custom js when building the release.
  • Load most js in the footer. Even with 15 – 20 js files a page will load a lot faster when most are in the footer. In theory we can load all but jQuery in the footer. There’s a ticket and patch for the script loader to do this. However in practice that will interfere with many plugins that load any of the default js files on admin pages. Seems that if we load jQuery and any jQuery UI parts in the head, the great majority of plugins won’t be affected. Another option would be to queue all UI parts for the footer but move them to the head if a plugin loaded js lists them as dependencies (that would complicate the script loader a bit).
  • Setting custom caching headers in .htaccess. Although this may not work on all servers, chances are that the great majority of installations would benefit. There are several settings that can be added: the “expire far in the future” is a must, either configuring or disabling Etags for the js, css and image files is advisable, also several of the HTTP 1.0 cache control headers would be beneficial. Of course this would need testing on different production servers, but it would degrade gracefully (just wouldn’t work), so counting it as “must implement”.
  • Adding all js and css files in both compressed and uncompressed state and setting the server (.htaccess) to use the compressed versions whenever possible. This would greatly improve the initial loading of all scripts (cold cache), but is not as trivial to set up as the cache control headers. Still worth a try even if not all WordPress installations would benefit. It is possible to set the server to compress “on the fly” or compress by using php, but both methods use a lot more of server CPU time/memory on each page load. Since this affects only cold cache hits, not sure if it’s worth it. The typical user case for the admin is the same user on the same computer and in the same browser accessing the admin at least several times per week. So making sure caching works best is a priority.
  • Concatenating all default js files on per page basis so there’s only one js file to load. This combined with compressing the file would give the fastest loading time for both cold and hot cache, although for hot cache with proper cache control the difference is almost unnoticeable. It is possible to do this when building the release and include two versions of each file: compressed and uncompressed, then use .htaccess to output the compressed version when possible. However when there is a plugin that loads js and depends on other default js files, the performance degrades quickly and most blogs seem to have at least one such plugin. The workaround is to dynamically generate the concatenated file for each page, compress it and store it on the server. That would mean doing something similar to WP Super Cache but only for the js and css files in the admin. There seem to be at least one plugin that attempts to do this, also several regular WordPress contributors are interested in making such plugins. Perhaps for now it’s better to leave this for a plugin as there seem to be many server configurations where it would be difficult to set up or won’t work properly. We can also add some hooks in script loader to facilitate this if needed.

In terms of performance the concatenating and compressing of all js and css files for each page gives the best results, closely followed by the loading of most js files in the footer. If we decide not to do the concatenating/compressing, we should revisit it in about a year (for WordPress 3.0?) as most Web hosts would have upgraded to php 5 by then. The actual php version wouldn’t affect this, but it seems that while upgrading the hosts also improve their server and php configurations too.