October 19, 2009

Combine & Minimize JavaScript using Ruby

AC shared with me this great way of combining many .js files to one big file. I am not sure if all the code was his or if some he found, so credit to whoever helped out with this. This is really a great and easy way to do this, and you can run this on a postscript or even from NAnt if you wanted. In order to use it, you will first need to download and install some software:
  1. Java
  2. Ruby (http://rubyinstaller.rubyforge.org/wiki/wiki.pl)
  3. RubyGems (http://rubyforge.org/frs/?group_id=126 & unzip to lcoation)
  4. command line > gem install rake
  5. command line > gem install rio
For those that want to know how to install Gems:
  • command line > ruby.exe c:\rubygems-1.3.1\setup.rb
Finally, make sure you have E:\Ruby\bin; (change E: to your drive) as a path variable as it makes things easier.

For the code below, I need to download jslint.js, jsmin.js, pack.js, and packer.js and store them in the same folder as well.

You then have a batch file with has just one word: rake. You run this batch file (which is in the same directory as your rake file explained below)

Now, the code is all in one little Rakefile:
require 'rio'

$rhino_compile_enabled = false
$minify_enabled = true
$jslint_enabled = false
$output_dir = "out"

puts "Starting..."

def get_files
files = []

files << as_is("http://yui.yahooapis.com/combo?2.5.2/build/yahoo-dom-event/yahoo-dom-event.js")
files << as_is("http://yui.yahooapis.com/combo?2.5.2/build/yahoo-dom-event/yahoo-dom-event.js&2.5.2/build/container/container-min.js&2.5.2/build/cookie/cookie-beta-min.js&2.5.2/build/json/json-min.js&2.5.2/build/element/element-beta-min.js&2.5.2/build/datasource/datasource-beta-min.js&2.5.2/build/connection/connection-min.js&2.5.2/build/charts/charts-experimental-min.js")

files << minify("../WebApp/js/diag.js")
files << as_is("../WebApp/js/jquery-1.3.1.min.js")
#add more files here

end

def as_is(file_path)

task file_path do
end

file_path
end

def minify(file_path)
mkdir_if_not_exist "#{$output_dir}/min"
min_path = get_min_path(file_path)

file min_path => file_path do
do_jslint file_path
do_minify file_path, min_path
end

min_path
end

def do_minify(file_path, min_path)
if $minify_enabled
`java -cp build/js.jar org.mozilla.javascript.tools.shell.Main build/min.js #{file_path} #{min_path}`
else
rio(min_path) < rio(file_path)
end
end

def do_jslint(file_path)
return unless $jslint_enabled

puts "jslint #{file_path}"

mkdir_if_not_exist "#{$output_dir}/tmp"
mkdir_if_not_exist "#{$output_dir}/jslint_errors"
tmp = "#{$output_dir}/tmp/jslint.tmp.js"

rio(tmp) < rio('jslint-options.js')
rio(tmp) << rio(file_path)

errors = `java -cp build/js.jar org.mozilla.javascript.tools.shell.Main build/jslint.js #{tmp}`

unless /jslint: No problems found/.match(errors)
rio("#{$output_dir}/jslint_errors/#{File.basename(file_path)}.err") < errors
end
end

def get_min_path(file_path)
"#{$output_dir}/min/" + File.basename(file_path) + ".min"
end

def mkdir_if_not_exist(dir_name)
Dir.mkdir dir_name unless File.exist? dir_name
end

def do_rhino_compile(file_path)
return unless $rhino_compile_enabled

puts "Rhino compiling..."
`java -cp build/js.jar org.mozilla.javascript.tools.jsc.Main #{file_path}`
puts "Rhino compilation done."
end

def get_combined_path
"#{$output_dir}/combined.js"
end

task :combine => get_files do
mkdir_if_not_exist "#{$output_dir}"
combined = get_combined_path

rio(combined) < "
/*
* Combined JavaScript.
* #{Time.now}
*/
"

get_files.each do |file_path|

puts "Combining: #{file_path}"
rio(combined) << "

/************************************************************************
* Source: #{file_path}
************************************************************************/

"
rio(combined) << rio(file_path)

puts 'next...'
end
end

task :rhino_compile do
do_rhino_compile get_combined_path
end

task :copy_combined do
rio("../WebApp/Combined/combined.js") < rio(get_combined_path)
end

task :default => [:combine, :copy_combined]
Thanks AC for this.

No comments:

Post a Comment