Hulk Smash – A Javascript Minifier in Perl

You’d like to have the fastest website out there, but you also want the coolest interactions and functions that come with pages and pages of javascript or jQuery code. That is going to be a problem. One thing that slows your site down, is asking the server to retrieve multiple other files. With each file, there is time required to negotiate the connection, request the file, and then receive it. If you were to pile all of that code into one small file, you could cut your site load time.

We all know this by now, and there are a ton of solutions for such a thing, Grunt, Gulp, etc. Most of them are build tools for processing a bunch of parts into an online application, and most of them are awesome. I started trying to decide which one to use, then remembered that I probably didn’t want to install additional bits on my production server if I didn’t need to. Then I came across this nice little Perl module to minify javascript. So created this handy little tool in Perl to stack all of my local javascript files into one file, then crunch them down into on neat little file.

So here it is if you’re interested in giving it a try.

Step 1: Prerequisites

You’ll have to be running Perl of course, which comes standard on most Linux, Unix and Mac systems. You’ll also need to have the Javascript:Minifier module installed, which is a little less likely.

Here is what I found to work on Ubuntu and Mac:

cpan App::cpanminus

You’ll have to answer a few simple prompts if you’ve never used cpan before, but they’re pretty straight forward.

Then install the Perl module in question.

cpanm Javascript::Minifier

Step 2: Put the Hulk Smash file on your server

Open your text editor of choice, paste the following code into it, and save it to your server. Before you save it though, make sure to customize it for your needs. You’ll want to choose names for the one large file to store your uncompressed javascript in, and the final compressed file. You’ll also want to change the names of the javascripts to include in your process. I left in a few of the ones I use for example.

Then go ahead and save it. I named mine “hulk-smash.pl”. It will be easier if your javascript files are all in one directory, and you can put this in that same directory, but not required of course. If the files are not in the same directory as hulk-smash.pl, then you’ll need to add which directory they’re in to the file names in the script.

#!/usr/bin/perl -w
#
#  PROGRAM: Concatenate a set of JS Files and then Minify the resulting file
#  by Paul Cushing at RektProductions.com 

use JavaScript::Minifier qw(minify);

# Output Files
$output = 'all.js';             # Uncompressed concatenated javascript file
$min_output = 'all.min.js';     # Final concatenated and minified file

# Files To Concatenate and Minify
@js_files = (   'jquery.backstretch.min.js',
                'typeahead.min.js',
                'modernizr.js',
                'smooth-scroll.js'
);


   open(OUT, '>', $output) or die "Could not open file: '$output' $!";

   $report = sprintf("%-50s %-20s\n", "Filename", "File Size");
   $report .= sprintf("%-50s %-20s\n", "--------", "---------");
   FILE: foreach (@js_files) {
      $filename = $_;
      $filesize = -s $_;

      open(FILE, '<', $_) || ((warn "Can't open file $_\n"), next FILE);

      while () {
         print OUT $_;
      }
      close(FILE);

    # $report .= $filename . "\t\t\t" . $filesize . "\n";
     $report .= sprintf("%-50s %-10s\n", $filename, $filesize);
     $totalsize += $filesize;
   }
   close OUT;

# Minify the result
open(ALLJS, $output) or die "Could not open file: '$output' $!";
open(MINJS, '>', $min_output) or die "Could not open file: '$min_output' $!";

minify(input => *ALLJS, outfile => *MINJS);
close(ALLJS);
close(MINJS);

# Results Output
$minsize = -s $min_output;
print "\n                  *********************";
print "\n                  *    Hulk Smash!    *";
print "\n                  *********************\n";
print $report;
print "\n";
printf("%-50s %-10s\n", "Total Input Size", $totalsize);
printf("%-50s %-10s\n", "New Filesize", $minsize);
$bytesSaved = $totalsize - $minsize;
$percentSize = $minsize / $totalsize * 100;
printf("%-50s %-10s\n", "Bytes saved", $bytesSaved);
print "Your new file is ";
printf("%.1f", $percentSize);
print "% the size of the originals.\n\n";

Step 3: Run It

Now that the script is in place, you run it. On most systems, you just have to invoke the Perl engine and then call the script.

perl hulk-smash.pl

If you’re not running as the administrator, you might have to throw a ‘sudo’ in front of that so the script can create or edit the files as needed.

Here’s what it looks like on my system:

hulk-screen

So here is a solution that doesn’t require a new language, framework, or resource hungry system. Perl is likely already on your server and you can just run this script each time you change something in your page’s javascript files. Let me know if you run into snags and I’m happy to help if I can.