uglifyjs-webpack-plugin是一个webpack的压缩插件,它的内部是基于UglifyJS,今天就来看看UglifyJS的简单使用。

UglifyJs完整的参数配置,可以去看它的文档: UglifyJS文档,(如果英文不好,可以去看中文文档: UglifyJS中文文档)。UglifyJs的使用有两种,一种是命令行,还有一种是在NodeJs中使用,我们这里只看NodeJs中的参数配置。我们着重看看里面比较难理解的配置:

(因为UglifyJs不支持es6,因此还有另外一个叫terser-webpack-plugin的插件,它的核心是terser.js,terser.js实际上是UglifyJs克隆版+支持es6。参数在UglifyJs的基础上增加了一些es6的配置。文档地址: terser)

Minify options

它指的是UglifyJS.minify(code, options);中的options的配置,它的所有可配置选项如下:

{
    warnings: false,
    parse: {
        // parse options
    },
    compress: {
        // compress options
    },
    mangle: {
        // mangle options
        properties: {
            // mangle property options
        }
    },
    output: {
        // output options
    },
    sourceMap: {
        // source map options
    },
    nameCache: null, // or specify a name cache object
    toplevel: false,
    ie8: false,
}

(注:以下代码全部运行在nodeJs环境中)

toplevel

默认false,如果设置为true,对全局方法/变量同时采取压缩/混淆,压缩表现为:若全局变量/方法没有被使用过,直接删除;若全局方法使用过一次,直接将它暴露在外层:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(first,second){console.log(first+second);};function hello(first,second){console.log(first+second);};",
    'file2.js': 'name(3,4);',
    'file3.js': 'var x={name:1};console.log(x);',
};
var result = UglifyJS.minify(code, {
        toplevel:true,
});
console.log(result.code);
/*
结果:
var o,l;o=3,l=4,console.log(o+l);console.log({name:1});
*/

上面我们定义了两个方法,一个name,一个hello,压缩结果中并没有hello,因为这个方法没有使用过,被删除了;我们看到name方法的定义已经没有了,反而是里面的内容直接暴露出来了。

混淆表现为:若一个全局方法使用了两次以上,那么不会暴露在全局中两次,还是会保留那个方法,只不过方法名会被混淆:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(first,second){console.log(first+second);};function hello(first,second){console.log(first+second);};",
    'file2.js': 'name(3,4);name(1,2);',
    'file3.js': 'var x={name:1};console.log(x);',
};
var result = UglifyJS.minify(code, {
        toplevel:true,
});
console.log(result.code);
/*
结果:
function o(o,n){console.log(o+n)}o(3,4),o(1,2);console.log({name:1});
*/

nameCache

这个属性用来记录那些被混淆的字符对应原来的哪个字符:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(first,second){console.log(first+second);};",
    'file2.js': 'name(3,4);',
};
var cache = {}
var result = UglifyJS.minify(code, {
        nameCache: cache,
        mangle: {
            toplevel: true,
        },
});
console.log(result.code,cache);
/*
结果:
function o(o,n){console.log(o+n)}o(3,4); { vars: { props: [Object: null prototype] { '$name': 'o' } } }
*/

我们传入一个cache,结果中可以看到方法结果中的o对应原来的name。

nameCache这个属性是可读可写的,刚才的操作我们可以认为cache被写入内容,我们可以设定好内容,等待读取:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(first,second){console.log(first+second);};",
    'file2.js': 'name(3,4);',
};
var cache = {
        vars:{
            props:{
        '$name': 'A',
            }
        }
};
var result = UglifyJS.minify(code, {
        nameCache: cache,
        mangle: {
            toplevel: true,
        },
});
console.log(result.code,cache);
/*
结果:
function A(o,n){console.log(o+n)}A(3,4); { vars: { props: [Object: null prototype] { '$name': 'A' } } }
*/

我们先设定好变量name混淆的变量(A),我们可以看到,混淆的结果中,name果然变成了A。

Compress options

是Minify options中compress的具体配置参数。

toplevel

这个相当于Minify options配置toplevel中的压缩部分,和Minify options中toplevel不同的是,如果一个全局方法使用了两次以上,方法名不会被压缩:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(age,name){console.log(age+name);};",
    'file2.js':'name(10,"zc");name(20,"ls")',
};
var result = UglifyJS.minify(code, {
    compress: {
        toplevel:true,
    },
});
console.log(result.code);
/*
结果:
function name(n,e){console.log(n+e)}name(10,"zc"),name(20,"ls");
*/

dead_code

移除不可达代码,默认是开启的,所谓不可达代码,例如return;throw;break;continue;后面的代码,我们先来看看如果关闭这个功能:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(first,second){first+=4;return first;first+=5;};",
    'file2.js': 'name(1,2);',
};
var result = UglifyJS.minify(code, {
    compress: {
        dead_code: false,
    },
});
console.log(result.code);
/*
结果:
function name(n,e){return n+=4;n+=5}name(1,2);
*/

上面代码中return后面还有一个表达式,如果我们关闭了dead_code功能,那么这个表达式不会被抹去,如果为true,那么就会抹除return后面的表达式。

drop_console

删除代码中的console.*语句,例如console.log,console.info等:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(age,name){console.log(age+name);console.info(age+name);};",
    'file2.js':'name(10,"zc");',
};
var result = UglifyJS.minify(code, {
    compress: {
            drop_console:true,
    },
});
console.log(result.code);
/*
结果:
function name(n,a){}name(10,"zc");
*/

我们可以看到,console.log和console.info已经都被删除了。如果想删除特定的,例如只想删除console.log,可以指定pure_funcs,它用来指定某个方法是纯函数,纯函数就是只干一件事的函数,它的删除对外部环境不会有任何影响。

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(age,name){console.log(age+name);console.info(age+name);};",
    'file2.js':'name(10,"zc");',
};
var result = UglifyJS.minify(code, {
    compress: {
            pure_funcs:['console.log']
    },
});
console.log(result.code);
/*
结果:
function name(n,o){console.info(n+o)}name(10,"zc");
*/

上面就只删除了console.log,保留了console.info。

unused

默认为true,删除没有引用的方法或者变量,注意这里删除的不是全局的方法/变量,而是局部的方法/变量,我们将unused设置为false:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(age,name){var x=1;console.log(age+name);};",
};
var result = UglifyJS.minify(code, {
    compress: {
            unused:true,
    },
});
console.log(result.code);
/*
结果:
function name(n,o){console.log(n+o)}
*/

虽然全局的方法name并没有被使用,但是它并不会被删除,因为unused影响的是局部的方法/变量。

global_defs

全局范围将一个词变成另一个词:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(age,name){console.log(age+name);};",
};
var result = UglifyJS.minify(code, {
    compress: {
        global_defs: {
            '@console.log': 'console.info'
     },
    },
});
console.log(result.code);
/*
结果:
function name(n,o){console.info(n+o)}
*/

上面将console.log变成了console.info,注意被替换词的前面要加@,否则替换的结果会被打上双引号。

Mangle options

是Minify options中mangle的具体配置参数。

toplevel

这个相当于Minify options配置toplevel中的混淆部分:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "function name(age,name){};",
    'file2.js':'var arr=[1,2]'
};
var result = UglifyJS.minify(code, {
        mangle: {
            toplevel: true,
        },
});
console.log(result.code);
/*
结果:
function n(n,a){}var a=[1,2];
*/

上面的全局方法name没有使用过,但是依然被压缩了,因为这里的toplevel只负责压缩全局方法/变量,不管是否使用过。

Mangle properties options

这个是上面Mangle options内部的配置:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "var obj={foo:'zc',zdd:20};obj.foo+=10;",
};
var result = UglifyJS.minify(code, {
        mangle: {
            properties: {
//                debug:true
            }
        },
});
console.log(result.code);
/*
结果:
var d={d:"zc",o:20};d.d+=10;
*/

这个属性开启后(哪怕是个空对象),就会对混淆map的key(内部会规避混淆document等已知的key,例如name等)。

它有一个debug属性,开启后,被替换的key上将会变成_$f$_这种形式(左右两个加上了标识符),这样便于区别那些被替换了。

Output options

是Minify options中output的具体配置参数:

beautify

美化输出的结果,默认都是输出一行,使用beautify后,代码可读性大大提高:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "var obj={foo:'zc',zdd:20};obj.foo+=10;",
};
var result = UglifyJS.minify(code, {
        output: {
            beautify:true,
        }
});
console.log(result.code);
/*
结果:
var obj = {
    foo: "zc",
    zdd: 20
};
obj.foo += 10;
*/

ascii_only

如果代码中含有ascii码,默认会转成字符:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "var obj={foo:'\u4e11',zdd:20};obj.foo+=10;",
};
var result = UglifyJS.minify(code, {
        output: {
        }
});
console.log(result.code);
/*
结果:
var obj={foo:"丑",zdd:20};obj.foo+=10;
*/

上面代码中有一个\u4e11,在转换后直接变成了中文,如何阻止默认转换呢?设置ascii_only:true:

var UglifyJS = require("uglify-js");
var code = {
    "file1.js": "var obj={foo:'\u4e11',zdd:20};obj.foo+=10;",
};
var result = UglifyJS.minify(code, {
        output: {
    ascii_only: true,
        }
});
console.log(result.code);
/*
结果:
var obj={foo:"\u4e11",zdd:20};obj.foo+=10;
*/

这样保证输出的还是ascii码。

comments

传 true 或 "all"保留全部注释,传 "some"保留部分。

回到顶部
我要评论

所有评论

返回
邮箱:
绑定
取消
×

我要评论

回复:

昵称:(昵称不超过20个字)

图片:

邮箱:
绑定邮箱后,若有回复,会邮件通知。
提交
还可以输入500个字