← home

jQuery 1.9.1, Yuglify, and UglifyJS

Here's a fun production bug we hit today at Zapier. As with many frontend-heavy sites, we use an asset pipeline to manage our static assets. We compile Javascript, compile CSS, combine frontend HTML templates, minifiy everything, then ship it up to Amazon S3.

We received a report that the site wasn’t “loading” on Firefox. Since we use Backbone for most of our internal application pages, that meant the user was stuck on our fallback loading GIF animation. The user hit a Javascript runtime error on page load. Again, Firefox only on this bug (Chrome and IE were strangely fine). Here is the exception I saw thrown for every AJAX request we fired:

o is not a function

Keep in mind this is minified code so o might vary depending on what UglifyJS decided to use as a replacement variable. This error occurred whether I ran production jQuery 1.9.1 (minified already) or development jQuery 1.9.1 (unminified) through our asset pipeline.

I was able to narrow down the cause to some default setting in Yuglify (a lightweight wrapper around UglifyJS 1.x). I bumped our UglifyJS version to the latest 2.x series but discovered that Yuglify was incompatible with this series. The final result was to remove Yuglify completely and tell Django Pipeline to use UglifyJS 2.x and CSSMIN directly. Here is what my final settings.py file looked like:

##################################
#### FRONTEND DJANGO PIPELINE ####
##################################

# npm install -g cssmin
PIPELINE_CSS_COMPRESSOR = 'pipeline.compressors.cssmin.CSSMinCompressor'
PIPELINE_CSSMIN_BINARY = '/usr/bin/env cssmin'
PIPELINE_CSSMIN_ARGUMENTS = ''

# npm install -g uglify-js
PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.uglifyjs.UglifyJSCompressor'
PIPELINE_UGLIFYJS_BINARY = '/usr/bin/env uglifyjs'
PIPELINE_UGLIFYJS_ARGUMENTS = ''

And viola! Once all our Javascript assets ran through Uglify 2.x directly, we didn’t see any problems. I suspect this is because of either:

  1. Some better internal compression scheme in the UglifyJS 2.x series or
  2. UglifyJS 2.x is no longer minifying variable names by default