Let's say you want to debug a javascript issue in your Rails application. Easy enough. You can use a browser tool such as Firebug to set a breakpoint and trace through the live code. Well, let's throw a wrench into the situation and let's say that you need to do this in your production environment, which is using the asset pipeline, which has compressed all of your beautifully crafted javascript into a single application.js file. This just became a lot harder because all of your javascript has been minified/compressed and no longer maintains it's nice, human readable structure that you coded it in.
Wouldn't it be nice to be able to set a url parameter (?debug=true) and immediately serve your uncompressed assets? If that were the case you'd be able use your browser tools (Firebug) to set some breakpoints and trace through live code in your production environment. Well, here's how I did it...
Create two javascript manifest files. One that will be compressed and one that will be left uncompressed. I named mine application.js and application-debug.js
// application.js
//= extjs-all
//= openlayers
//= other_javascript_files
/**
* application-debug.js
* disable_asset_compression <== this is important later!
**/
//= extjs-all-debug
//= openlayers-debug
//= other_javascript_files
Create a before_action in your application_controller.rb that checks for your "debug" url parameter. If the "debug" url parameter exists, set a "debug" instance variable that can be read from your root layout file (application.html.erb).
class ApplicationController < ActionController::Base
before_action :debug_assets
def debug_assets
if params[:debug]
@debug = true
end
end
# ...
end
Inside the head tags of your root layout file (application.html.erb), check for the "debug" instance variable. Based on it's existence, serve up the uncompressed or compressed version of your javascript.
<% if @debug %>
<%= javascript_include_tag "application-debug“ %>
<% else %>
<%= javascript_include_tag "application" %>
<% end %>
Pretty simple so far, right? What happens when you to need precompile the assets and you've set your js_compressor as Uglifier? Uglifier will compress both versions of your javascript manifests. To fix this, we'll need to override a couple methods in Uglifier by defining our own js_compressor that inherits from Uglifier.
First, define ConiditionalUglifier in your application's lib directory. Notice that the override looks for the string "disable_asset_compression" in a comment block in your manifest file. When it sees this string, it will disable compression for that manifest.
class ConditionalUglifier < Uglifier
def initialize(options = { })
options.merge(:comments => :all)
super(options)
end
def compress(source)
if source =~ /disable_asset_compression/
source
else
super(source)
end
end
end
Next, set your js_compressor in the appropriate environment files (production and wherever else your precompile assets).
# config/environments/production.rb
# ...
config.assets.js_compressor = ConditionalUglifier.new
# ...
That's it! Precompile and deploy. To serve the uncompressed versions of your javascript assets, simply put "debug=true" as a parameter in your url. Happy debugging!