I've been using Google's closure compiler, and I've heard that Google is also using it in their products.
Recently, I looked at Google Maps' compressed source code, and found out that string literals are pre-defined at the top.
# I've beautified in order to make it more readable
this._ = this._ || {};
(function (_) {
var window = this;
try {
'use strict';
:
var daa;
var caa;
var baa;
var aaa;
aaa = "\x00";
baa = "\n\nBrowser stack:\n";
caa = "\n//# sourceURL=";
daa = '\nUrl: <a href="view-source:';
:
I think this is a good idea, because string literals written directly in source code will make hacking much more easier, and this solution can prevent it. Also, it can reduce script file size if long strings are used repeatedly.
I want to use this optimization in my project too, but I have no idea what options I should set to compiler. Are there any Closure compiler's options? Or else, are developers using some external tools to do this?
This is covered in the project FAQ: Closure Compiler inlined all my strings, which made my code size bigger. Why did it do that?
Related
I have a requirement to minify the constant values in the javascript project I am working on.
Currently I define the constants as something like this:
export const Constants = {
I_AM_CONSTANT: 'hello',
ANOTHER_CONSTANTS: 10,
YET_ANOTHER_CONSTANTS: false,
NO_MORE_CONSTANT: 'end'
};
and I put this object into a separate file.
Then I use UglifyPlugin of WebPack to minify the codes.
But what I get is something like
e.Constants = {
I_AM_CONSTANT: 'hello',
ANOTHER_CONSTANTS: 10,
YET_ANOTHER_CONSTANTS: false,
NO_MORE_CONSTANT: 'end'
};
It's like no minification effect at all. Can anyone tell me what is the correct way to do the minifications for these constants? How can I change my code? I also would like to know some best practice of writing constant values in javascript if possible.
You can't minify what you have because the minified won't know where there to be used. If you used injection correctly though the consuming code can be minified, e.g.
var closure = function(constants){
//constants used lots in here.
}(e.Constants);
could safely be minfied to
var closure = function(c){
//c used lots in here.
}(e.Constants);
e.constants gets closed over into a local variable constants, this can be happily minified to c as the minifer knows it's scope, it's inside the closure and is injected.
Where as this:
function closure(){
//e.constants used lots in here
}
can't be minified because any change to e.constants would be breaking.
I'm trying to interpret this piece of Javascript code. What is the use of the $ and _ signs here? In particular, is $ an alias for the JQuery library, and does this also apply for $set?
Template.postEdit.events({
'submit form': function(event) {
event.preventDefault();
var currentPostId = this._id;
var postProperties = {
url: $(event.target).find('[name=url]').val(),
title: $(event.target).find('[name=title]').val()
}
Posts.update(currentPostId, {$set: postProperties}, function(error) {
if (error) {
// display the error to the user
throwError(error.reason);
} else {
Router.go('postPage', {_id: currentPostId});
}
});
}
});
Explaination
$ and _ are mostly appended in Javascript variables to give more readability and to be more distinguishable ( visually most of the times ) from other variables. They are just conventions used by JS developers. Not necessary you've to use them. Major libraries/frameworks like Jquery, Angular like to follow this style in their frameworks.
Usage of $
Jquery have wrapped their features in $ . If you have included jQuery in your application, then $ used alone stands for jquery Object. Jquery being a really popular modern library, have somehow snatched the variable in JS. But its not like they have licensed the variable ( Just think, if variable name could be licensed, development would be more painful than it is now :p ), its more like they have dominated the use of $.
var selector = $('.someclass'); /* This is jquery object similar to
var selector = jQuery('.someclass') */
var $somestring = 'some string'; // Here $ character is appended to a variable.
//It doesn't adds any special behavior to the variable.
Some people have make good use of $, check it out here.
A naive developer who have used too much or the only library as JQuery in his lifespan is prone to this confusion. When he sees source code from framework like AngularJS, he tries to relate things with his former love jQuery. In Angular variables like $scope, $compile, etc, they seem confusing to him, as they have heavily appended $ to name their objects. Its just another name, you can write code with or without it. Angular uses this convention to distinguish variables from local to special objects. Big guns always try to dominate their conventions over the developer community. Can't blame them much, its for the betterment for all
Usage of _
Riding in similar vogue bandwagon, _ was nearly snatched by another useful ( really ? we can live without it ) library called Underscore Js . So they use the _ as their Underscore object, or mostly developers are to be blamed for this abuse, as they have paved its path to the vanity. But we can't blame developers for this, they were just using following good naming conventions.
var _myName = 'Who Cares'; // similar to $ no special behavior
var currentPostId = this._id; // In your case it seems
Well _ is mostly used by developers to distinguish the variables as private data members of their class, but only naming doesn't guarantee the access level. A good post briefly explaining for this is here
The best part is that, all the special characters that are allowed in Javascript to create distinguishable variable names are already invaded by biggies. So no more confusion. It is understandable why underscore invaded _ as their supremo, it stands for its meaning. But I am still curious why $ was chosen by jQuery. It doesn't even rhyme with it. No distant relation, it seems jQuery just took it as their property. I don't find any post explaining their invasion over it.
Sorry for being so dramatic, comic and sarcastic. Feel free to downnvote if it does not suit your appetite. Here to just help and make this space more interesting.
P.S : A list of valid characters for the naming convention used in JS
is explained here
I'm using a jQuery plug-in and Google Closure Compiler. The problem is that there's a bug in the plug-in when I add the URL of that plug-in into the compilation, the compilation fails. So I want to create an extern for that plug-in. Basically, I'm only using 1 object and 2 methods from the entire library; something like this:
var TheObject = $.plugin({...});
var SomeVar = TheObject.someName.otherName(SomeString, {
prop1: [...],
onError: function () {...}
});
TheObject.SomeMethod();
I looked at the doc on Google's website but it's written from a confusing "what-it-is" perspective and I need a simple "how-to" perspective on how to do this. What do I need to do to create an extern for what I have?
Thanks.
Here you go:
How to Write Closure-compiler Extern Files – Part 1 The Basics
jQuery Plugins and Closure-Compiler
I haven't had time to finish out the series on creating externs. If this isn't enough for your project, I'll revisit the topic.
So I've been struggling on and off with this question for a while and I've come up with a working solution for others who have a plug-in they want to use in their code with closure compiler: instead of doing an extern, just use strings, like this:
var TheObject = $['plugin']({...});
var SomeVar = TheObject['someName']['otherName'](SomeString, {
'prop1': [...],
'onError': function () {...}
});
TheObject['SomeMethod']();
That may not work for everybody but this worked for me and saved me a great deal of hassle in terms of writing an extern. I found the doc online to be very confusing: either written by techies who explain what things are, but now how to use them, or written in a professorial tone, with not many empirical examples. I hope this answer will help others.
I often need to rename variables when refactoring code, which I currently do in a somewhat hacky way using regexs - I end up having to come with silly text workaround workarounds for the lack of actual structure, eg, rename 'req' to 'request' and avoid side effects with similar names like 'require'.
Thinking about this stuff: it's kind of like modifying the DOM with regexs: it just doesn't work.
I've learnt about ASTs and code structure modification tools like Esprima. Is there a tool to rename variables, Esprima based or otherwise?
1. grasp.js
It looks like http://graspjs.com/ does exactly this.
grasp selector --replace replacement file.js
For example, to rename 'el' to 'element':
grasp '#el' --replace 'element' index.js
Official grasp.replace docs.
2. vscode
Visual Studio Code also includes a real replacement tool. Just right click a token and choose rename symbol.
I know you've been asking for 'a tool'; but I think it's better to use just esprima itself and the various general purpose tools on top of esprima, and roll your own renamer. Because it's really really easy, and then you have more control. Here is a complete example in just 12 lines of code. It uses escodegen and estraverse, both on github, and, as far as I can see kind of 'the standard' to use in conjunction with esprima. While esprima essentially gives the parse function string -> abstract syntax tree, escodegen essentially gives the reverse of that, i.e. abstract syntax tree -> string. And estraverse 'walks the tree' with the traverse method, thus helping to analyze or modify it.
Here the code:
function rename(code, renamingObj){
var ast = esprima.parse(code);
function callback(node){
if (node.type==='Identifier') {
if (node.name in renamingObj){
node.name = renamingObj[node.name];
}
}
}
estraverse.traverse(ast, { enter: callback });
return escodegen.generate(ast);
}
Testcase:
function blah(x,y){
var difference = x + y;
var product = x - y;
var sum = x * y;
return 42;
}
var renamingObj = {
sum : 'product',
difference : 'sum',
product : 'difference'
};
run it:
rename(blah.toString(), renamingObj)
output:
function blah(x, y) {
var sum = x + y;
var difference = x - y;
var product = x * y;
return 42;
}
I would say, if you have something special to do, it's easier to modify above code than sifting through some tool documentation.
Our JavaScript Formatter/Obfuscator will do this reliably. It parses JavaScript, builds an AST, and either prints a pretty version, or an ugly (obfuscated) version. [The reason these are together is because pretty and ugly are opposite sides of the same coin!).
One of the things it does is scramble (whole) identifier names. By using the AST, it only renames "whole identifiers"; it won't confuse "req" with "require", or modify string or comment content by accident.
You can tell it to build a map of all identifier names, and then rename them all to themselves; change just one, and you get your rename effect. The identifier map looks like this:
x -> y
p -> q
...
directing that x gets renamed to y, p to q, etc. You want:
x -> x
p -> q
...
to change just p to q. Its pretty easy to produce the identity map
as your starting place.
I wouldn't say this is convenient, but it does work. It obviously doesn't
know anything about scopes. (someday!).
See my bio for details. Many SO moderators hate tool questions, and they especially seem to dislike it when I provide a tool answer that includes a link to the tool. So you'll have to track down the link yourself, sorry. (Complain on Meta if you think this is dumb).
As I'm sure most of the JavaScripters out there are aware, there's a new, Christmas-themed js1k. I'm planning on entering this time, but I have no experience producing such minified code. Does anyone know any good resources for this kind of thing?
Google Closure Compiler is a good javascript minifier.
There is a good online tool for quick use, or you can download the tool and run it as part of a web site build process.
Edit: Added a non-exhaustive list of tricks that you can use to minify JavaScript extremely, before using a minifier:
Shorten long variable names
Use shortened references to built in variables like d=document;w=window.
Set Interval
The setInterval function can take either a function or a string. Pass in a string to reduce the number of characters used: setInterval('a--;b++',10). Note that passing in a string forces an eval invokation so it will be slower than passing in a function.
Reduce Mathematical Calculations
Example a=b+b+b can be reduced to a=3*b.
Use Scientific Notation
10000 can be expressed in scientific notation as 1E4 saving 2 bytes.
Drop leading Zeroes
0.2 = .2 saves a byte
Ternery Operator
if (a > b) {
result = x;
}
else {
result = y;
}
can be expressed as result=a>b?x:y
Drop Braces
Braces are only required for blocks of more than one statement.
Operator Precedence
Rely on operator precedence rather than adding unneeded brackets which aid code readability.
Shorten Variable Assignment
Rather than function x(){a=1,b=2;...}() pass values into the function, function x(a,b){...}(1,2)
Think outside the box
Don't automatically reach for standard ways of doing things. Rather than using d.getElementById('p') to get a reference to a DOM element, could you use b.children[4] where d=document;b=body.
Original source for above list of tricks:
http://thingsinjars.com/post/293/the-quest-for-extreme-javascript-minification/
Spolto is right.
Any code minifier won't do the trick alone. You need to first optimize your code and then make some dirty manual tweaks.
In addition to Spolto's list of tricks I want to encourage the use of logical operators instead of the classical if else syntax. ex:
The following code
if(condition){
exp1;
}else{
exp2;
}
is somewhat equivalent to
condition&&exp1||exp2;
Another thing to consider might be multiple variable declaration :
var a = 1;var b = 2;var c = 1;
can be rewritten as :
var a=c=1,b=2;
Spolto is also right about the braces. You should drop them. But in addition, you should know that they can be dropped even for blocks of more expressions by writing the expressions delimited by a comma(with a leading ; of course) :
if(condition){
exp1;
exp2;
exp3;
}else{
exp4;
exp5;
}
Can be rewritten as :
if(condition)exp1,exp2,exp3;
else exp4,exp5;
Although it's not much (it saves you only 1 character/block for those who are counting), it might come in handy. (By the way, the latest Google Closure Compiler does this trick too).
Another trick worth mentioning is the controversial with functionality.
If you care more about the size, then you should use this because it might reduce code size.
For example, let's consider this object method:
object.method=function(){
this.a=this.b;
this.c++;
this.d(this.e);
}
This can be rewritten as :
object.method=function(){
with(this){
a=b;
c++;
d(e);
}
}
which is in most cases signifficantly smaller.
Something that most code packers & minifiers do not do is replacing large repeating tokens in the code with smaller ones. This is a nasty hack that also requires the use of eval, but since we're in it for the space, I don't think that should be a problem. Let's say you have this code :
a=function(){/*code here*/};
b=function(){/*code here*/};
c=function(){/*code here*/};
/*...*/
z=function(){/*code here*/};
This code has many "function" keywords repeating. What if you could replace them with a single(unused) character and then evaluate the code?
Here's how I would do it :
eval('a=F(){/*codehere*/};b=F(){/*codehere*/};c=F(){/*codehere*/};/*...*/z=F(){/*codehere*/};'.replace(/function/g,'F'));
Of course the replaced token(s) can be anything since our code is reduced to an evaluated string (ex: we could've replaced =function(){ with F, thus saving even more characters).
Note that this technique must be used with caution, because you can easily screw up your code with multiple text replacements; moreover, you should use it only in cases where it helps (ex: if you only have 4 function tokens, replacing them with a smaller token and then evaluating the code might actually increase the code length :
var a = "eval(''.replace(/function/g,'F'))".length,
b = ('function'.length-'F'.length)*4;
alert("you should" + (a<b?"":" NOT") + " use this technique!");
In the following link you'll find surprisingly good tricks to minify js code for this competition:
http://www.claudiocc.com/javascript-golfing/
One example: (extracted from section Short-circuit operators):
if (p) p=q; // before
p=p&&q; // after
if (!p) p=q; // before
p=p||q; // after
Or the more essoteric Canvas context hash trick:
// before
a.beginPath
a.fillRect
a.lineTo
a.stroke
a.transform
a.arc
// after
for(Z in a)a[Z[0]+(Z[6]||Z[2])]=a[Z];
a.ba
a.fc
a.ln
a.sr
a.to
a.ac
And here is another resource link with amazingly good tricks: https://github.com/jed/140bytes/wiki/Byte-saving-techniques
First off all, just throwing your code into a minifier won't help you that much. You need to have the extreme small file size in mind when you write the code. So in part, you need to learn all the tricks yourself.
Also, when it comes to minifiers, UglifyJS is the new shooting star here, its output is smaller than GCC's and it's way faster too. And since it's written in pure JavaScript it should be trivial for you to find out what all the tricks are that it applies.
But in the end it all comes down to whether you can find an intelligent, small solution for something that's awsome.
Also:
Dean Edwards Packer
http://dean.edwards.name/packer/
Uglify JS
http://marijnhaverbeke.nl/uglifyjs
A friend wrote jscrush packer for js1k.
Keep in mind to keep as much code self-similar as possible.
My workflow for extreme packing is: closure (pretty print) -> hand optimizations, function similarity, other code similarity -> closure (whitespace only) -> jscrush.
This packs away about 25% of the data.
There's also packify, but I haven't tested that myself.
This is the only online version of #cowboy's packer script:
http://iwantaneff.in/packer/
Very handy for packing / minifying JS