前端代码压缩工具--closesure compiler

closesure-compile:
用来压缩加密js代码的工具
 
一个典型的简单用例:
 
使用指令:
java -jar closure-compiler-v20171023.jar --js test-closesure.js --js_output_file min.js --compilation_level ADVANCED_OPTIMIZATIONS
 
初始版本:
function sayHello(name) {
alert("Hello " + name);
}
 
sayHello('zhangsan');
sayHello('lisi');
 
class Student {
constructor(name, age) {
this.info = {};
this.info.name = name;
this.info.age = age;
}
sayName() {
alert(this.info.name);
}
}
 
// var stu = new Student('wangxiaoya', 29);
// stu.sayName();
代码体积:373 字节
 
压缩后45字节,内容如下:
alert("Hello zhangsan");alert("Hello lisi");
可以看到压缩时,删除空格换行,移除无用代码(class Student),简化函数(sayHello)
 
如果添加如下代码:
var stu1 = new Student('wangxiaoya', 29);
stu1.sayName();
var stu2 = new Student('gebaini', 29);
stu2.sayName();
var stu3 = new Student('wangzhi', 29);
stu3.sayName();
 
压缩之后:
function a(b){this.a={};this.a.name=b;this.a.b=29}alert((new a("wangxiaoya")).a.name);alert((new a("gebaini")).a.name);alert((new a("wangzhi")).a.name);
 
1.函数的参数名将发生变化
2.类中的属性名称可能被加密
2.如果由于所有人使用一样的age,则不会被传入,而是直接使用29
 
修改下代码:
var stu1 = new Student('wangxiaoya', 20);
stu1.sayName();
var stu2 = new Student('gebaini', 19);
stu2.sayName();
var stu3 = new Student('wangzhi', 29);
stu3.sayName();
stu3.sayAge();
 
压缩后:
function a(c,d){this.a={};this.a.name=c;this.a.b=d}alert((new a("wangxiaoya",20)).a.name);alert((new a("gebaini",19)).a.name);var b=new a("wangzhi",29);alert(b.a.name);alert(b.a.b);
 
这次参数被传入,不过属性名依旧被加密
 
使用注意事项:
1.尽可能不要使用eval
在上例中,使用eval,加密后代码崩掉,原因是编译器不会替换eval中的引用
eval("var stu4 = new Student('liqin', 20);stu4.sayName();");
加密后:
eval("var stu4 = new Student('liqin', 20);stu4.sayName();");
 
2.注意类的方法和属性可能被省略和重命名,因此暴露给用户的属性尤其需要注意这一点
var stu2 = new Student('gebaini', 19);
stu2.sayName();
alert(stu2.info.age);
 
加密后:
var b=new a("gebaini",19);alert(b.a.name);alert(b.a.b);
 
类名不要用字符串定义属性
class Student {
 
constructor(name, age) {
this.info = {};
this.info.name = name;
this.info['age'] = age;
}
 
var stu2 = new Student('gebaini', 19);
stu2.sayName();
alert(stu2.info['age'])
 
由于两处不一致,加密后出错
function a(d, e) {
this.a = {};
this.a.name = d;
this.a.age = e
}
var b = new a("gebaini", 19); alert(b.a.name); alert(b.a.b);
 
3.全局变量需要加window或者就都不要加
window.aa = {
'name': 'zhangsan',
'age': 20,
'address': 'xian',
'hobby': 'swim',
}
 
alert(window.aa);
变成:
window.a={name:"zhangsan",age:20,address:"xian",hobby:"swim"};alert(window.a);
 
或者
var aa = {
'name': 'zhangsan',
'age': 20,
'address': 'xian',
'hobby': 'swim',
}
 
alert(aa);
变成:
alert({name:"zhangsan",age:20,address:"xian",hobby:"swim"});
 
如果使用不一致,则错误
var aa = {
'name': 'zhangsan',
'age': 20,
'address': 'xian',
'hobby': 'swim',
}
 
alert(window.aa);
 
变成:
alert(window.a);
 
4.在除了constructor prototype外的方法使用this
var foo = {};
foo.bar = function (a) { this.bad = a; };
foo.bar("hello");
 
var foo$bar = function (a) { this.bad = a; };
foo$bar("hello");
 
5.两个静态方法重名
class A {
/** @nocollapse */
static create() {
return new A();
}
};
class B {
/** @nocollapse */
static create() {
return new B();
}
};
 
var ctor = new Date().getFullYear() > 2012 ? A : B;
ctor.create();
 
之后变成
function a(){}a.create=function(){return new a};function b(){}b.create=function(){return new b};(2012<(new Date).getFullYear()?a:b).create();
 
不加注释,两个方法都会被忽略
function a(){}function b(){}(2012<(new Date).getFullYear()?a:b).create();
 
6.使用三方库
如果压缩的文件使用了第三方的库,三方库不需要加密,那么只编译此文件会报错
var a = createDom();
var b = createDome();
document.append(a);
document.append(b);
 
test-closesure.js:58: ERROR - variable createDom is undeclared
var a = createDom();
^^^^^^^^^
 
test-closesure.js:59: ERROR - variable createDome is undeclared
var b = createDome();
^^^^^^^^^^
 
 
此时可以指定一个声明文件,告诉closesure,不需要更改此方法的名字,也不会报错
java -jar closure-compiler-v20181008.jar --js test-closesure.js --js_output_file min.js --compilation_level ADVANCED_OPTIMIZATIONS --externs aaa.js
 
声明文件aaa.js
function createDom(){
}
 
 
 
 
posted @ 2022-07-03 18:37  内心澎湃的水晶侠  阅读(379)  评论(0编辑  收藏  举报