Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

JavaScript Minifier Utility Posted


I've been working a bunch with JavaScript over the last few weeks, building a number of library type components that have script dependencies. I'm still bouncing back and forth between the idea of using embedded Resources with ASP.NET (ie. WebResource.axd) a compressed resources using a custom Script Compression module I posted some time ago, or just using plain old .js files in a designated directory and serving them from there.

If I end up serving disk based JavaScript Resources I want to compress these resources and I've taken over the jQuery common approach of using a main file with a .js extension and also a compressed version with .min.js. These compressed files remove all whitespace and comments from JavaScript files thus reducing the size of the JavaScript by about 30%-40% on average. The good news about this is that you can be more verbose in your JavaScript code and reduce the size. This ratio holds even if you (or the Web Server) add GZIP compression ontop of the minimized module.

There are lots of tools out there for compressing JavaScript, some online etc. In fact, I'd been using Dan Wahlin's Java Script string compression utility for a while to do conversions manually, but I wanted something that I can use right in my VS project as an Open With option and that can directly compress files on disk as well as strings and do batch conversions.

So I created a quick and dirty utility that does the job using Douglas Crockfords JavaScript Minifier (which is also what Dan used) and wrapped it with a small WinForms app that can also run via Command Line and do batch conversions. I also made a few modifications to the original compression class to support string to string conversion so it can also be used for things like my script compression module.

The resulting WinForms app looks like this:

You can use this app either as a ClickOnce Application online or by downloading the tool and source code (.NET 2.0 required):

The tool supports using wildcards so it can automatically pack all .js files in a given directory in batch by using *.js for the filename. If the output filename is not specified the output files are assumed to be created with a .min.js extension.

You can also use this tool via the command line:

jsMinifier.exe [InputFile] [OutputFile] [NoUI]

The output file is optional and if not specified defaults to the same name as the input file (or files if *.js is used for the filenames) with a .min.js extension. In batch conversions you can specify an alternate extension by using .compressed.js for the output file for example (ie. without any sort of filename - just the output extension). NoUI can be used as the second or third parameter to specify command line only operation. Otherwise the WinForm is displayed with default values set.

I liketo use it from within Visual Studio interactively, so I've got it tied to the Open With menu:

Which makes short work of updating JavaScript files. If you want a more automated approach you can also add a post build task to do the conversions automatically say in the Release build only.

Script Compression

As I mentioned the compression provided by this routine tends to cut roughly 30-40% of most of the script files I've thrown at it, depending how terse the code is. The key advantage is that whitespace and comments are stripped so if you're coding JavaScript you don't have to count bytes for simple formatting like I've been doing often in the past with some of my library code.

I tend to use this with the assumption that every java script file I load in a library has both uncompressed and compressed versions available and so the library/component code trying to load resources in Debug mode will  use the uncompressed version and the compressed version when running in release build which works well and can get some of the same benefits that a dynamic Web Resource approach can offer.

I'm still debating what works better - using Web Resources or external files. I'm leaning more towards the Web Resource approach whenever possible because it give you as the developer more control, but recently when I posted the  jQuery Calandar ASP.NET component several folks commented that they thought it a bad idea to stick script resources into an ASP.NET assembly. I don't fully agree but I do see the point regarding potential resource and version conflicts, so I pretty much came to the conclusion that it's best to always provide explicit URLs for all resources and having them default to an embedded Web Resource that can be overridden as needed (or be omitted altogether if it's already loaded). And that's where this sort of pre-compression comes in. I think even in combination with GZIP it's still worth it to trim off the fat as it were especially if we want to code JavaScript that is actually readable and not trying to eek out every last byte in favor of size <g>...

Make Donation
Posted in ASP.NET  JavaScript  


Feedback for this Post

 
# re: JavaScript Minifier Utility Posted
by John November 26, 2007 @ 9:00pm
Rick, this topic is very much on my todo list. And I'm sure many others.

Have you looked into any further compression by replacing variable names in the script?
It seems to me if we all follow the convention of using an underscore for private methods and varibles the we should be able to loop through and replace all of them with two or three letters without issue.
eg:
datepicker._adjustDate could be:
datepicker._a1

The benifit I see is we can use more verbose meaningfull names for private methods and varibles without the penalty.

Other notes I've made is that you can use a return instead of a semi-colon to end a line, this makes your code the same size but easier to debug, visual studio hates one giant line of javascript. For the sake of a couple of charactors (blank lines for comments) you could even have matching line numbers with the original code.
I currently use:
http://www.xtreeme.com/javascript-optimizer/

Also as part of our deployment (completly manual currently) we put all the .js files into a single file. It seems that browsers do have a performance hit for downloading seperate files. Since we put every javascript "class" in a seperate file, as this makes them easier to manage and develop as a team, we notice a big difference going from 20+ to 1.

John.
# re: JavaScript Minifier Utility Posted
by Rick Strahl November 26, 2007 @ 10:12pm
@John, yeah there are a number of compressors that do this, but it gets a lot more complicated to do this because when you do name conversion you need to in effect parse the JavaScript code and understand what's a variable etc.

I certainly wouldn't attempt to build this and even some of the popular compressors that do do this tend to fail and get it wrong on occasion with some scripts which is a lot more scary. I think that the optimal compression vs. complexity formula is stripping white space and comments and then let GZIP compression do its thing. GZIP will optimize duplicated names away reasonably well so further name compression isn't going to buy a ton when GZIP is applied.

If you're looking for ultra compact JS file, there are several popular tools (http://dean.edwards.name/weblog/2007/08/js-compression/) which uses code to decompress the actual JavaScript code, but it requires client side resources to accomplish this and you may actually have slower load times because of the decompression.

The biggest issue though is that I've tried several of these tools before and they flat out failed to properly decompress the JavaScript which failed to load or errored out at runtime. That's really a risk I'm not willing to take...
# re: JavaScript Minifier Utility Posted
by Damien Guard November 27, 2007 @ 3:43am
Looks like <a href="http://damieng.com/blog/2007/11/27/shrinking-js-or-css-is-premature-optimization">premature optimization</a> to me.

[)amien
# re: JavaScript Minifier Utility Posted
by Josh Stodola November 27, 2007 @ 6:18am
Awesome Rick, I was looking for something just like this. Until now I was also using an online utility. I also found Dean Edwards' packer (or rather the strictness of it) to be a pain in the ass. The rules are whack! Seriously, who terminates a function with a semicolon?!

Thanks for posting this.
# re: JavaScript Minifier Utility Posted
by rbfigueira November 27, 2007 @ 7:05am
Hi Rick,

You application have one Encoding problem. The app eats some characters and amending others who have problems of accentuation

For example:

Before compress: alert ("Anulação!!")
After compress: alert("Anulao!!")

Cheers
# re: JavaScript Minifier Utility Posted
by KnaveT November 27, 2007 @ 7:50am
For validation of your script files, you can try http://www.jslint.com. It is capable of detecting missing semicolons, which is the deal breaker when using the packer code from Dean Edwards.

The valiator isn't perfect, but it works for simple validation.

Knave
# re: JavaScript Minifier Utility Posted
by Abdu November 27, 2007 @ 9:11am
I think Javascript obfuscators do a good job of compressing without problems. I haven't used any but I've looked at commercial software where the JS was practically impossible to read and understand because of all the renaming and packing that was done.
# re: JavaScript Minifier Utility Posted
by Rick Strahl November 27, 2007 @ 4:22pm
@Damien - Point taken. However this is not what I'd consider premature anything since this can become part of the build process and part of component design. Use of the optimized library is optional and would only apply to components that automatically took advantage of the minimized versions. The savings may seem small but percentage wise it's still 20-40% which is significant especially when you're dealing with lots of javascript resources IMHO.

@rbfigueira - yeah you're right. Actually I didn't check this out in detail - I made the assumption that the minify code I used from Douglas Crockford worked, but it turns out it's not dealing with file encoding properly (ie. not detecting UTF-8 formatting). I've fixed this in the online app and the download now.
# re: JavaScript Minifier Utility Posted
by Atif Aziz November 27, 2007 @ 6:37pm
Hi Rick. I've had Crockford's JSMin ported to C# and available since 2005 off my site as project Jazmin. See http://www.raboof.com/projects/jazmin/. The reason I'm mentioning it here (FWIW) is that it also comes with an MSBuild task for direct integration into a Visual Studio project file and therefore the build process. I also checked in the MSBuild task into the open source MSBuild Community Tasks Project (http://msbuildtasks.tigris.org/) as the JSCompress task. The benefit of the latter is that you get a whole bundle of handy tasks as opposed to a single stand-alone task in a single assembly.
# re: JavaScript Minifier Utility Posted
by Brennan Stehling November 28, 2007 @ 6:59am
http://brennan.offwhite.net/blog/2007/08/26/packer-for-net-302-released/

You may also want to try the utility I put together that wraps Packer and JSMin for the command-line and for an MSBuild Task. I am not sure how much different it is from the one Atif Aziz created called JSCompress. My version allows you to choose a mode between Packer or JSMin based on your needs. You can also combine many source files into a single source script.

And for more info on compressing JavaScript, you may want to read a blog entry I wrote a few months back that goes into various aspects of bandwidth and gzip...

http://brennan.offwhite.net/blog/2007/02/25/how-big-is-your-javascript-library/
# re: JavaScript Minifier Utility Posted
by blogging developer January 29, 2008 @ 10:08am
Another free online tool for compressing javascript is <a href="http://www.compressjavascript.com" title="free online tool for compressing javascript">http://www.compressjavascript.com</a>

cheers,
blogging developer
# re: JavaScript Minifier Utility Posted
by gav August 17, 2008 @ 4:27pm
I had file access errors when the source js file was checked into source control. Updating the GetFileEncoding with this seems to fix it:

FileStream file = new FileStream(srcFile, FileMode.Open, FileAccess.Read);
# re: JavaScript Minifier Utility Posted
by Jason P Sage August 23, 2008 @ 3:58pm
"Seriously, who terminates a function with a semicolon?!"

I DO! It's standard for C++, and has been valid syntax for Javascript since day one.. possibly a requirement for all I know in early versions. Regardless, javascript is modeled in many ways to follow C++ syntax (curly brackets, for loop constructs, etc.) It shows good Character :)

No Harm in not doing it - but its not bad form to do it... and if you're a C++ programmer - its second nature.

--Jason
# re: JavaScript Minifier Utility Posted
by Magnolia8575 December 24, 2008 @ 2:08pm
A simple online javascript minifier can be found at
http://netspurt.com

This one is based on dojo's shrink safe.
# re: JavaScript Minifier Utility Posted
by Matt May 08, 2009 @ 1:56pm
yet again I come to solve a problem, decide on the best way to solve it, and then find that Rick Strahl has already solved it. Stop stealing my ideas before I have them!
# Script Combine in una'Applicazione MVC
by Il blog di ugo lattanzi June 04, 2009 @ 1:31am
Script Combine in una'Applicazione MVC
# re: JavaScript Minifier Utility Posted
by David January 12, 2010 @ 5:51am
Works a treat!
Note: In the copy I just downloaded, the documented "NoUI" option isn't recognised. From the source code it looks like this has changed to "autoprocess".
# re: JavaScript Minifier Utility Posted
by Mike Hankey February 01, 2010 @ 5:08pm
Nice utility thanks.

Mike
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014