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.

WeChatFE
WeChatFE
WeChatFE
Master UglifyJS: Proven Techniques to Shrink JavaScript Size

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‑computed

Rule 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 operand

2 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

code compressionJavaScript minificationUglifyJS
WeChatFE
Written by

WeChatFE

Tencent WeChat Public Platform Frontend Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.