Pragmatic Bookshelf Website Performance

I’ve been a big fan of the Pragmatic Bookshelf series, in particular their monthly online magazine. The magazine are downloadable in PDF, .mobi, and .epub formats, and browsable online in HTML format.

Browsing through the latest couple of issues, I noticed a distinct slowness as some of the images were downloaded. This is usually a hint that a high resolution image is being referenced, but being “cropped” down to a smaller size with the height/width attributes in the HTML. For example, see this story about Ruby Bundler and look at the red ribbon image. The source image is 693×693 but is being displayed as 190×190. It’s also a very high quality level and weighs in at 203KB – compare with the page itself which is only about 10KB. Resizing this JPEG image in PhotoShop dropped the size down to 6KB (or 3KB at medium quality), with no visible difference on the web page.

With those possible savings, I looked closer at the rest of the Magazines pages to see what other performance improvements could be gained, following “best practices” advice from tools like YSlow, PageSpeed, and Rather than trying to solve everything at once, I’ve suggested improvements in priority order. I’ve also focused on content served via because that will be the easiest to change. The 3rd-party widgets like Digg and Reddit can be dealt with later, if at all. (Performance improvements on 3rd-party widgets usually need to come from the 3rd-party itself.)

Step 1: Images Sizes

As a first step, update the publishing process to reduce image sizes required in all page downloads. Specific changes:

  • Re-size images correctly for their use on the page (i.e., don’t re-size via HTML height/width)
  • For JPEG images, save at the lowest quality that still looks good (e.g., Medium or 50)
  • For PNG images, convert to 8-bit if quality is acceptable
  • Run YSlow (lossless compression) on all images and switch to the compressed versions
  • Switch GIF to PNG where recommends (typically for very small images, excludes any using alpha transparency)

Step 2: Image Expiration and Hosting

Continuing to improve the image delivery, there are a couple of specific changes that can help here:

  • Add “expires” settings for images – at least a week, but preferably a “far future” expiration date with version increments in the filename (header_v1.jpg, header_v2.jpg, etc.)
  • Move images currently served on to one of the or domains (which do have image expiration set correctly); also seems to be a bit slower when serving images

Step 3: Better Handling of CSS and JavaScript

On the CSS/JS side, there is some room for improvement in the number and size of these static files:

  • Reorganize and combine the CSS files, removing the use of “@import” as well; currently there are 7 unique CSS files for the core page design (i.e., not counting 3rd-party widgets). These could be combined with the use of integrated media selectors rather than having multiple entries
  • Minify CSS and JavaScript (e.g., using YUICompressor)
  • Add versioning to CSS/JS files and set a far-future expires time

Step 4: Miscellaneous

Finally, here are some additional fine-tuning adjustments that will also help:

  • Confirm whether or not store.js is needed on all pages – remove if not
  • Convert images in page templates to use CSS Sprites
  • Switch Google Analytics to load asynchronously and include JS file at page bottom
  • Change source of diggthis.js from to to avoid extra redirect
  • Change source of button.js from to to to avoid extra redirect

Hopefully the above list gives a good roadmap for the improvements that can be made on a site like this. Most of this hopefully doesn’t require very significant changes to their build process, but should give dramatic improvements for site visitors.