Master UglifyJS: Proven Techniques to Shrink JavaScript Size
This article explains how UglifyJS can dramatically reduce JavaScript file size by applying expression pre‑computation, operator shortening, dead code removal, and other advanced compression rules, illustrated with clear before‑and‑after code examples for each optimization.
0 Preface
For JavaScript, the most direct way to improve network download performance is to reduce the size of JS files. This article introduces UglifyJS compression details in two parts.
Part 1
Expression compression
Operator shortening
Removing unused declarations/references
Part 2
While‑loop compression
Conditional expression compression
Statement block compression
IF‑branch optimization
For easy comparison, before‑and‑after code snippets are provided; variable names are not obfuscated, and each rule is demonstrated separately.
1 Expression Compression
Rule 1.1 Pre‑compute expressions
Replace compile‑time calculable expressions with their result, keeping the shorter of the original and the result.
Before:
var expr1 = 1+1;
var expr2 = 1/3;After:
var expr1 = 2;
var expr2 = 1/3; // 0.3333333333333 is longer than 1/3, so not pre‑computedRule 1.2 Optimize true/false
Normally true becomes !0 (saves 2 chars) and false becomes !1 (saves 3 chars). Directly converting to 1 or 0 would change type semantics, but it is safe when the value participates only in == or != comparisons.
Before:
var expr1 = true;
var expr2 = false;
true == A;
false == A;After:
var expr1 = !0;
var expr2 = !1;
1 == A;
0 == A;Rule 1.3 Use short‑circuit characteristics
Expressions like true && A() or false || A() can be reduced to just A() because the logical operators return the second operand when the first is truthy.
Before:
true && A();
false && A();
true || A();
false || A();After:
A(); // && returns second operand
!1; // && returns first falsy operand
!0; // || returns first truthy operand
A(); // || returns second operand2 Operator Shortening
Rule 2.1 Replace ===/!== with ==/!= when both operands are strings or booleans
When the two operands share the same type, the strict operators can be safely shortened.
Before:
"object" === typeof A;
true !== b instanceof B;After:
"object" == typeof A;
true != b instanceof B;Rule 2.2 Convert a = a + b to a += b
The assignment can be shortened if the left‑hand variable appears as the first operand of a binary operation on the right‑hand side.
Before:
a = a + b;
c = c >>> d;
a = b + c;After:
a += b;
c >>>= d;
a = b + c;Rule 2.3 Negate non‑! operators when the negated form is shorter
For example, !(a >= b) becomes a < b, and !!!a simplifies to !a.
Before:
!(a >= b);
!!!a;After:
a < b;
!a;3 Remove Unused Declarations/References
Rule 3.1 Remove duplicate directive strings
When nested scopes contain the same directive (e.g., "use strict"), the inner one can be removed.
Before:
function A(){
"use strict";
function B(){
"use strict";
}
}After:
function A(){
"use strict";
function B(){
}
}Rule 3.2 Remove unused function parameters
Parameters that are never referenced can be dropped, but the order of remaining parameters must stay unchanged.
Before:
function A(a, b, c){
b++;
}After:
function A(a, b){
b++;
}Rule 3.3 Drop redundant function names in expressions
If a function expression does not reference its own name (no recursion), the name can be omitted.
Before:
(function A(){ A(); })();
(function B(){ c++; })();After:
(function A(){ A(); })();
(function(){ c++; })();Rule 3.4 Remove empty or single‑statement blocks
Blocks that contain no statements or only one statement can be eliminated.
Before:
while(f){ { A(); } }
while(f){ {} }
if(A){ B(); }After:
while(f) A();
while(f);
if(A) B();Rule 3.5 Omit the final break in a switch
The last break; in a switch case/default can be removed unless it carries a label.
Before:
switch(A){
case 1: break;
case 2: break;
}
label: switch(A){
case 1: break;
case 2: break label;
}After:
switch(A){
case 1: break;
case 2: // break omitted
}
label: switch(A){
case 1: break;
case 2: break label; // labeled break kept
}Rule 3.6 Remove unused labels
Labels that are never referenced can be eliminated.
Before:
label1: var a = 1;
label2: while(true){ break label2; }After:
var a = 1;
label2: while(true){ break label2; }Rule 3.7 Drop unnecessary toString calls
UglifyJS removes redundant toString() calls only when the --unsafe flag is used.
Before:
(typeof A).toString();
("A"+"B").toString();
var expr = "str".toString();After:
(typeof A);
"AB";
var expr = "str";Tips
The article is long and split into two parts; the next part will cover while‑loop compression, ternary expression compression, statement block compression, and IF‑branch optimization, which are the most extensive and interesting UglifyJS rules.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
