JSMin+ version 1.4

By crisp on Sunday 24 July 2011 00:12 - Comments (21)
Category: JSMin+, Views: 23.802

Version 1.4 of JSMin+ is available for download. Because we are still actively using JSMin+ at Tweakers.net we did make some minor improvements since I released version 1.3 for the public now more than 2 years ago, but I never felt those improvements warranted a new public version. Until now.

This week I received an email from MediaWiki informing me that they imported JSMin+ into their code base as a library and they suggested some code changes, asking me if I would consider including them in the public version. Because these changes made sense I hereby am happy to oblige :)

That still would have made this only a very minor release, so I decided to fix at least one other major problem that has been reported to me several times: the fact that JSMin+ was quite memory-intensive, especially when minifying large (eg combined) javascript files.

To fix that I moved part of the minification process to the JS parser itself where it can minify chunks of the parse tree which can be disposed after that. I made this change in such way that it is still possible to get a complete parse tree from the JS parser.

From a test I ran with the unminified source code of JQuery 1.6.2 memory usage went down from 40+MB to only around 8MB :)

Complete changelog for JSMin+ 1.4:
  • Remove an empty statement and the closing ?>
    (as per suggestion by platonides of MediaWiki: http://www.mediawiki.org/wiki/Special:Code/MediaWiki/92560)
  • Remove dynamic creation of OP_* and KEYWORD_* defines and declare them on top
    (as per suggestion by platonides of MediaWiki: http://www.mediawiki.org/wiki/Special:Code/MediaWiki/92563)
  • Reduce memory footprint by minifying by block-scope (within the parser itself)
  • Some more byte-saving improvements, eg:
    • 100000 => 1e6
    • return !foo => return!foo
    • return -1 => return-1
  • Some small performance improvements:
    • split up handling of string literals by quotestyle (simplifies the regular expression used)
    • change matching of numeric tokens to be more efficient
Known issues:
  • JScript conditional compilation support is (still) not complete yet
  • Performance can still be improved even more
  • No support yet for variable-name minification
  • No ES5 support
Note that we *do* take patches for any of a.m. issues!

The latest version is available on http://tweakimg.net/files/upload/jsminplus-1.4.zip

You can read more about JSMin+ in the announcement post.

Volgende: About the cube again 05-'12 About the cube again
Volgende: Adoptie, daar kies je toch zelf voor? 05-'11 Adoptie, daar kies je toch zelf voor?

Comments


By Tweakers user Spider.007, Sunday 24 July 2011 10:28

Wow, the reduced memory usage is a very nice accomplishment! Also, mediawiki's inclusion of your library is a great confirmation of the quality of this library.

Thanks for this update!

[Comment edited on Sunday 24 July 2011 10:28]


By Tweakers user YopY, Sunday 24 July 2011 10:42

I'd really really really like to see a big comparison between JS minifiers and such technologies (or make one of my own), comparing compression speed, size, performance of resulting JS (some minifiers change the actual code), ease of use, etc. In the last few years, there's been a huge increase in popularity for Javascript and, resultingly, tools - see Github.

By Tweakers user Vold, Sunday 24 July 2011 12:05

Awesome project, really cool that it is also being used for one of the biggest websites in the world! Just looked at the code, but I was wondering what your advised usage of this script is.

I assume you don't use this script in realtime, but do you have a so to say "deployment to production" script that once minifies all the .js files? Or maybe a cron job at specific intervals? And if so, is the performance that important? Because the impact of the script remains really small if it is used so rarely...

Anyways, keep up the good work. :)

By Tweakers user Erkens, Sunday 24 July 2011 12:23

I use it during deployment, really nice to see this updated version. One of the reasons I use this minifier is that every function is on a seperate line, which makes debugging in a live situation not that hard!

By Tweakers user crisp, Monday 25 July 2011 01:05

Spider.007 wrote on Sunday 24 July 2011 @ 10:28:
Wow, the reduced memory usage is a very nice accomplishment! Also, mediawiki's inclusion of your library is a great confirmation of the quality of this library.

Thanks for this update!
Do note that MediaWiki is currently only using this library for it's JS parser to do automated syntax-checking. Afaik JSMin+ is the only existing (port of a) JS parser in PHP :)
They have some home-brew minifier for JS, which is less efficient but a lot faster...
YopY wrote on Sunday 24 July 2011 @ 10:42:
I'd really really really like to see a big comparison between JS minifiers and such technologies (or make one of my own), comparing compression speed, size, performance of resulting JS (some minifiers change the actual code), ease of use, etc. In the last few years, there's been a huge increase in popularity for Javascript and, resultingly, tools - see Github.
I think it depends on the use case which tool would fit best. I tried a lot of minifiers but couldn't find a decent one written in PHP at the time I wrote JSMin+. There was only a PHP port of Crockford's JSMin, but that tool dictated some code style that I couldn't fully agree with.

I know that JSMin+ does a better job at minification compared to JSMin, but it is around 5 times slower. Google Closure Compiler and YuiCompressor may be able to sqeesh out some more bytes (but I watch those projects closely :P), but they also have more options such as variable name minification. Only downside (for me) is: those libraries are not PHP-based.

Besides that I think it is very cool that I could put the Narcissus library written by Brendan Eich himself to good use :)
Vold wrote on Sunday 24 July 2011 @ 12:05:
Awesome project, really cool that it is also being used for one of the biggest websites in the world! Just looked at the code, but I was wondering what your advised usage of this script is.

I assume you don't use this script in realtime, but do you have a so to say "deployment to production" script that once minifies all the .js files? Or maybe a cron job at specific intervals? And if so, is the performance that important? Because the impact of the script remains really small if it is used so rarely...
I actually don't recommend doing minification on demand at all. Javascript files, being normally static, should best be served from a server that's dedicated and tuned to serving static files.

We actually run a script when checking out our trunk repository to our staging server which checks for changed JS and CSS files and performs minification (and also combines certain files). Those minified files can then be pushed to production when we do a release.

So indeed, performance is not much of an issue for us; minification is done only once and only when necessary.

[Comment edited on Monday 25 July 2011 01:50]


By Tweakers user jurp5, Monday 25 July 2011 07:59

You've seen https://github.com/mishoo/UglifyJS/? It's a minifier using node.js which compresses even better, and faster! than closure compiler :)

By Tweakers user crisp, Monday 25 July 2011 09:39

jurp5 wrote on Monday 25 July 2011 @ 07:59:
You've seen https://github.com/mishoo/UglifyJS/? It's a minifier using node.js which compresses even better, and faster! than closure compiler :)
It's not PHP-based :P

I briefly looked at it, but there are some things that I don't really like. First of all the number of open issues (:P). But secondly I don't like minifiers that actually change code (apart from syntax). Some of those minification tricks are known to have a negative performance impact. It also makes debugging more difficult.

By Tweakers user s.stok, Tuesday 30 August 2011 15:50

There is a PHP Port, but its still in development.
https://github.com/kbjr/UglifyJS.php

Nice to see there is a new version, I use it in https://github.com/roller...ork/Filter/cJSMinPlus.php

Variable-name minification is basically the only thing that is missing in JSMin+

By Treidge, Wednesday 31 August 2011 14:59

That's great, I have to stick for some time with JSMin because of memory issues, but now I think I can have another try with this one :P

By Stefan Galinski, Tuesday 06 September 2011 16:31

Thanks for this great minification tool! I have written an extension - called scriptmerger - for the CMS TYPO3 (http://typo3.org) that utilizes this library.

http://forge.typo3.org/projects/extension-scriptmerger

By Tweakers user jexus, Tuesday 24 April 2012 17:03

Small bug in the ASI process combined with a multiline comment:

code:
1
2
3
4
5
alert(function () {
    return /*
        Just a comment.
    */ 5;
}());

When minified the result is an alert box with '5' in it, while it should be 'undefined' since the multiline comment acts as a newline in this case.

The problem lies in scanNewlines not being inspected when checking multiline comments. Of course, it's a pretty much ridiculous use case, but I though it warranted a reply here. :)

[Comment edited on Tuesday 24 April 2012 17:03]


By Tweakers user crisp, Wednesday 25 April 2012 00:52

I checked with the original Narcissus code, and it actually is a bug in there as well. It's easy to fix though so I have made a note of it :)

By Tweakers user jexus, Wednesday 25 April 2012 17:32

I actually used a tiny hack to simulate the newline. :)


code:
1
2
3
4
5
6
7
                $this->lineno += $c = substr_count($match[0], "\n");

                if ($c > 0 && $this->scanNewlines) {
                    $input = "\n";
                    --$this->cursor;
                    break;
                }


Not the cleanest solution, but it works unconditionally.

I actually stumbled across this bug when checking UglifyJS's test cases againt my own adaption of JSMinPlus (https://github.com/rvanvelzen/MinifyJS).

Again, thanks for porting Narcissus, I have certainly enjoyed hacking stuff and creating a very powerful minifier. :)

By Tudor, Monday 07 May 2012 23:38

The file.tweakers.net link appears to freeze. So I can't download the library anymore. ;-( Can you fix the link, please?

By Tweakers user crisp, Tuesday 15 May 2012 00:01

Tudor wrote on Monday 07 May 2012 @ 23:38:
The file.tweakers.net link appears to freeze. So I can't download the library anymore. ;-( Can you fix the link, please?
Thanks, fixed that :) Location for version 1.4 is http://tweakimg.net/files/upload/jsminplus-1.4.zip :)

By luminarious, Sunday 10 June 2012 20:40

First, thank you for this library, it's rather handy. Unfortunately I ran into my first issue with JSMinPlus so far - unicode support. Javascript supports arbitrary unicode characters as valid function and variable names and I inherited a piece of code that makes use of that. Unfortunately, it seems the library is currently limited to ascii-only. Would it be a lot of work to upgrade it unicode-wise?

By Tweakers user crisp, Sunday 10 June 2012 21:06

luminarious wrote on Sunday 10 June 2012 @ 20:40:
[...]
Would it be a lot of work to upgrade it unicode-wise?
Luckily I recently received a patch that would make JSMinPlus unicode compliant and I intend to incorporate that in the next version. However, I can't tell when that will be unfortunately...

By Martin Tournoij, Monday 22 October 2012 11:06

This line of code:
(1).upto(5)

Gets compiled to:
1.upto(5)

Note the lost parenthesis around the 1, which causes an error:
Syntax error at line 1: unexpected character: U+0031
1.upto(5)

A workaround is to use:
var a = 1
a.upto(5)

By Qosg, Friday 15 February 2013 17:49

Hello,

I have found a bug breaking my website!

Where there are two IIFE next to each other, the removal of the semicolon of the first one will break the code, here is a working code:

(function($){
alert("it's working");
})(jQuery);

(function($){
alert("it's working");
})(jQuery);

But once minifed we get something like:

(function($){alert("it's working");})(jQuery)(function($){alert("it's NOT working");})(jQuery);

See? Why do you remove semicolons??? For saving ONE character you're breaking all the code!!!!!!!

Please fix this please, for now I have to manually minify my files with other tools.... so stupid :'(

By Qosg, Friday 15 February 2013 18:18

Update:

Actually, my last comment is not entirely true, this bug happens when merging multiple minified scripts together.

So if I have an IIFE in my script1 and another IIFE in my script2, and that I minify script1, then minify script2, then merge those 2 scripts into one file, then the error occurs.

This is because JSMin+ removes the last semicolon of each script, breaking any attempt to merge two scripts using javascript IIFE.

A temporary fix is to add the following at the end of each script:

function a(){} // Empty function placed at the end of the file to avoid a minification bug

I hope you're gonna fix this and release an update soon, because the space saved by removing ONE semicolon at the end of the script/file is ridicilus compared to the amount of trouble this causes, especially with the spreading of IIEF as a common use now: http://tech.myemma.com/ii...t-control-variable-scope/

Thank you for your work... and for fixing this!

By kas, Thursday 23 May 2013 14:22

The patch to support Unicode (http://www.mediawiki.org/wiki/Special:Code/MediaWiki/98281) works correctly less when a multi-byte Unicode character is cut :-(

Comments are closed