This new version of the compressor fixes a few bugs and optimizes string concatenations. You can now keep your code nicely formatted by concatenating string literals, but not suffer any performance hit. For example, the following code:
var url = ".../services/rest/" + "?method=flickr.test.echo" + "&format=json" + "&api_key=02b6a73df2c4a33c282f3d02fe5724e3" + "&callback=jsonCallback";
will become (↵ marks a line continuation)
var url = ".../services/rest/↵ ?method=flickr.test.echo&format=json↵ &api_key=02b6a73df2c4a33c282f3d02fe5724e3&callback=jsonCallback";
Also, note that, from now on, all YUI Compressor-related downloads will be done from a separate download page and not directly from this blog.
Download version 2.1 of the YUI Compressor
Another fine release! Keep up the good work.
Pingback: Ajax Performance » Quick follow-up: more YUI Compressor work
Pingback: CompressorRater: Compare the squeeze « outaTiME
Julien Lecomte:
Thanks again for your work on this. It is excellent.
In your comment on the 2.0 page, you mention two of my suggestions and the bug that you had already fixed in 2.1.
I have no problem not having the multiple filenames.
I think that accepting STDIN and STDOUT for the file arguments would be a big help. It would also make not having multiple filenames no big deal.
And line numbers for the warnings would be very useful. :-)
Thanks again!
I upgrade to version 2.1 the yuicompressor-maven-plugin. And I also add a goal to run jslint against js files.
Thank you Julien for your job.
Nice Work Julien! Someone was just mentioning it would be nice to have that feature, over on the ShrinkSafe blog at
It’s hard to keep up with you :) but I’ll be adding this version to the CompressorRater very soon.
Pingback: Ajax Girl » Blog Archive » CompressorRater: Compare the squeeze
In the CSS compressor, you made this change “Remove spaces before and after ‘(‘ and ‘)’ as in background:url(‘xxx’);”.
But, when I have a “background:url(‘xxx’) no-repeat;” the space before “no-repeat” is removed. This prevents the background from appearing in Internet Explorer.
@John
Thanks for reporting this. Due to the gravity of this bug, I just pushed version 2.1.1, available from the download page.
Pingback: YUI Compressor 2.1 Released » Chris Norton
Pingback: Ajaxian » CompressorRater: Compare the squeeze
Probably a slightly stupid question but anyway:
How hard would it be to have the compressor attack JS-namespaces and method-names? I find quite a portion of my code to be consisting of,”MyCompany.NamesSpaceOne.myFunction” stuff..
I’m feeling there’s a catch here, or?
@Fredrik
Yes, there is a catch (of course!) Prior to developing the YUI Compressor, I worked (in another company) on a compressor that was able to do just that: obfuscate everything! However, to accomplish that, we had to introduce all types of “hints” to tell the compressor the type of each variable, etc. The problem here can be summarized by the term “COST EFFICIENCY”: you want to get the biggest bang for your buck. If you need to spend many extra cycles debugging because you want to save an additional 10%, you are not taking the most efficient approach. Trust my experience!
Hi,
Is it possible to add (in a next version, no urgence) an option to keep header comments (if it contains “license” or “copyright” or “(c)”, to agree Copyrigth/Open Source license.
@David Bernard
This type of task is beyond the scope of the compressor. If you need to prepend some license or copyright information, use the
cat
command line utility, or if you use Apache Ant to build your application, use a nestedheader
element to theconcat
task.Regards
@David, just because your application has to carry the license doesn’t mean you have to put it in your .css file…
Julien, nice working on the string-concatenation constant folding case. When do we get generic constant propagation? :D
I requested the feature for third parties js and css files, with various licenses.
Some licenses require keep it and credit authors, eg :
“The collection is dual licensed with the MIT license and the GPL, which basically means you can use it for free for both non-commercial and commercial usage as long as you keep the copyright notice in each of Interface’s JavaScript source file.”
from interface elements for jQuery.
But may be, “minified” files could be considered like compiled ones.
Thanks for the replies.
@Julien
Ok, I do trust you. One of the major reasons I’m interested in, and have tried out your compressor, is the safety-factor. Only JsMin has previously handled our code without errors (and I’m not doing any evals withs..).
Though, the reason I pondered namespace & function mangling was that I kindof suspect the savings to be quit a bit larger than 10%. I guess I need to write some test..
Perhaps an option? -alias MyNamespace MN ?
Very nice, thanks for the update! Has anyone integrated this into an ANT task yet and if so, could you please explain how you did it or send me an example? Thanks.
@Jason
Keep watching this blog. You will get your answer in an upcoming article to be published within the next 2 weeks.
Hi,
pack:tag 2.4 has been released. It supports the YUI Compressor and the CSS Compressor. Check the website at:
Great compressors, keep up the good work.
Merci pour ce composant genial, je ne l’ai pas encore integre’ dans mon projet, mais ca ne saurait tarder, il me suffira juste de remplacer shrinksafe. Pour que ca marche pour moi il me faudra acceder a l’API Java, je suppose que javaScriptCompressorInstance.compress devrait faire l’affaire.
@Jason Collins
I posted an Maven/Ant automated compression example using rhino I implemented some time ago. It included optional conditional compression (compress only if files changed) and namespace “shrinkage” (as mentioned by Fredrik above).
I believe the YUI compressor + Maven plugin are the way to go, though.
Great work, guys!
Create a file called test.js with the following contents:
/*extern YAHOO, viv */
/*jslint undef: false, nomen: true, evil: false, undef: true, browser:
true, white: true */
(function () {
viv.example = function () {
};
viv.example();
YAHOO.example = function () {
};
YAHOO.example();
})();
Then execute yuicompressor like so and notice the WARNING.
$ bin/yuicompressor -charset utf-8 -warn test.js
[WARNING] Found an undeclared symbol: viv
(function (){viv —> .
This is strange. It didn’t complain about YAHOO, but complained about
viv. It’s almost as if someone added YAHOO to an exception list… ^_^
It should either complain about both or neither.
Alternatively, it could honor jslint’s extern declaration, which I’d
like even better.
Ciao!
@The Doctor What
Since all local variables are going to be renamed to a 1 (or 2, or 3) letter symbol, it tries to spot undeclared globals that are less then 3 letters in length (which is the case for “viv”) to avoid naming conflicts, and shows a warning. It does not care about undeclared globals that are 4 letters long or more (which is the case for “YAHOO”)
I am planning to make some improvements in that area.
Regards
Oh, okay. That makes sense. Obviously, knowing what variable names it can and cannot use would be better. Meanwhile, can you clean up the warning to say something like your message above?
Can’t you just have a function to generate the identifiers for you? Something like (in JavaScript, because I don’t do enough Java to be confortable):
var idengen = function () {
if (typeof (idengen.list) === ‘undefined’) {
idengen.init();
}
var count = 0;
var next = this.gen();
while (count
Then if you find an undefined global variable, then just call
idengen.seen(globalvar);
.Now that I think about it, it would be helpful to track all undifined global variables and then return them optionally with a command line param.
Ciao!
@The Doctor What
You should use JSLint. The YUI Compressor is in no way a replacement for JSLint.
Regards
Hi Julien
I’m building a website framework using js-compressors, and have come accross a problem that I can not find an answer for anywhere else. It seems like you are close to the guru in this area and thus I turn my hope for an answer to you.
The goal of the framework is to allow modules to be loaded on the fly, either in the background after the initial load has been done, or when the user requests an action/functionality that has not yet been used. When compressing I hide all unnecessary names by enclosing the total script in an anonymous function. This however obfuscates the names in the base js and the modules in different environments and thus they cannot use eachother. My question is thus if it is possible with the current compressors to set a starting obfuscation table of name=>obfuscated_name when compressing a new file and thus compress it like it was compressed in that environment? Using this approach compressed modules could be run inside the compressed environment by using eval.
Best regards
Kezzel
@Kezzel
Each module should export a set of global symbols. Simply omit the ‘var’ keyword in front of them, and they won’t obfuscated.
Hope this helps,
Julien