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的配置,它的所有可配置选项如下:

    1. {
    2.     warnings: false,
    3.     parse: {
    4.         // parse options
    5.     },
    6.     compress: {
    7.         // compress options
    8.     },
    9.     mangle: {
    10.         // mangle options
    11.         properties: {
    12.             // mangle property options
    13.         }
    14.     },
    15.     output: {
    16.         // output options
    17.     },
    18.     sourceMap: {
    19.         // source map options
    20.     },
    21.     nameCache: null, // or specify a name cache object
    22.     toplevel: false,
    23.     ie8: false,
    24. }

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

    toplevel

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(first,second){console.log(first+second);};function hello(first,second){console.log(first+second);};",
    4.     'file2.js': 'name(3,4);',
    5.     'file3.js': 'var x={name:1};console.log(x);',
    6. };
    7. var result = UglifyJS.minify(code, {
    8.         toplevel:true,
    9. });
    10. console.log(result.code);
    11. /*
    12. 结果:
    13. var o,l;o=3,l=4,console.log(o+l);console.log({name:1});
    14. */

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

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

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

    nameCache

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(first,second){console.log(first+second);};",
    4.     'file2.js': 'name(3,4);',
    5. };
    6. var cache = {}
    7. var result = UglifyJS.minify(code, {
    8.         nameCache: cache,
    9.         mangle: {
    10.             toplevel: true,
    11.         },
    12. });
    13. console.log(result.code,cache);
    14. /*
    15. 结果:
    16. function o(o,n){console.log(o+n)}o(3,4); { vars: { props: [Object: null prototype] { '$name': 'o' } } }
    17. */

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

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(first,second){console.log(first+second);};",
    4.     'file2.js': 'name(3,4);',
    5. };
    6. var cache = {
    7.         vars:{
    8.             props:{
    9.         '$name': 'A',
    10.             }
    11.         }
    12. };
    13. var result = UglifyJS.minify(code, {
    14.         nameCache: cache,
    15.         mangle: {
    16.             toplevel: true,
    17.         },
    18. });
    19. console.log(result.code,cache);
    20. /*
    21. 结果:
    22. function A(o,n){console.log(o+n)}A(3,4); { vars: { props: [Object: null prototype] { '$name': 'A' } } }
    23. */

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

    Compress options

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

    toplevel

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(age,name){console.log(age+name);};",
    4.     'file2.js':'name(10,"zc");name(20,"ls")',
    5. };
    6. var result = UglifyJS.minify(code, {
    7.     compress: {
    8.         toplevel:true,
    9.     },
    10. });
    11. console.log(result.code);
    12. /*
    13. 结果:
    14. function name(n,e){console.log(n+e)}name(10,"zc"),name(20,"ls");
    15. */

    dead_code

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(first,second){first+=4;return first;first+=5;};",
    4.     'file2.js': 'name(1,2);',
    5. };
    6. var result = UglifyJS.minify(code, {
    7.     compress: {
    8.         dead_code: false,
    9.     },
    10. });
    11. console.log(result.code);
    12. /*
    13. 结果:
    14. function name(n,e){return n+=4;n+=5}name(1,2);
    15. */

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

    drop_console

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(age,name){console.log(age+name);console.info(age+name);};",
    4.     'file2.js':'name(10,"zc");',
    5. };
    6. var result = UglifyJS.minify(code, {
    7.     compress: {
    8.             drop_console:true,
    9.     },
    10. });
    11. console.log(result.code);
    12. /*
    13. 结果:
    14. function name(n,a){}name(10,"zc");
    15. */

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(age,name){console.log(age+name);console.info(age+name);};",
    4.     'file2.js':'name(10,"zc");',
    5. };
    6. var result = UglifyJS.minify(code, {
    7.     compress: {
    8.             pure_funcs:['console.log']
    9.     },
    10. });
    11. console.log(result.code);
    12. /*
    13. 结果:
    14. function name(n,o){console.info(n+o)}name(10,"zc");
    15. */

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

    unused

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(age,name){var x=1;console.log(age+name);};",
    4. };
    5. var result = UglifyJS.minify(code, {
    6.     compress: {
    7.             unused:true,
    8.     },
    9. });
    10. console.log(result.code);
    11. /*
    12. 结果:
    13. function name(n,o){console.log(n+o)}
    14. */

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

    global_defs

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(age,name){console.log(age+name);};",
    4. };
    5. var result = UglifyJS.minify(code, {
    6.     compress: {
    7.         global_defs: {
    8.             '@console.log': 'console.info'
    9.      },
    10.     },
    11. });
    12. console.log(result.code);
    13. /*
    14. 结果:
    15. function name(n,o){console.info(n+o)}
    16. */

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

    Mangle options

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

    toplevel

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "function name(age,name){};",
    4.     'file2.js':'var arr=[1,2]'
    5. };
    6. var result = UglifyJS.minify(code, {
    7.         mangle: {
    8.             toplevel: true,
    9.         },
    10. });
    11. console.log(result.code);
    12. /*
    13. 结果:
    14. function n(n,a){}var a=[1,2];
    15. */

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

    Mangle properties options

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "var obj={foo:'zc',zdd:20};obj.foo+=10;",
    4. };
    5. var result = UglifyJS.minify(code, {
    6.         mangle: {
    7.             properties: {
    8. //                debug:true
    9.             }
    10.         },
    11. });
    12. console.log(result.code);
    13. /*
    14. 结果:
    15. var d={d:"zc",o:20};d.d+=10;
    16. */

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

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

    Output options

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

    beautify

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "var obj={foo:'zc',zdd:20};obj.foo+=10;",
    4. };
    5. var result = UglifyJS.minify(code, {
    6.         output: {
    7.             beautify:true,
    8.         }
    9. });
    10. console.log(result.code);
    11. /*
    12. 结果:
    13. var obj = {
    14.     foo: "zc",
    15.     zdd: 20
    16. };
    17. obj.foo += 10;
    18. */

    ascii_only

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "var obj={foo:'\u4e11',zdd:20};obj.foo+=10;",
    4. };
    5. var result = UglifyJS.minify(code, {
    6.         output: {
    7.         }
    8. });
    9. console.log(result.code);
    10. /*
    11. 结果:
    12. var obj={foo:"丑",zdd:20};obj.foo+=10;
    13. */

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

    1. var UglifyJS = require("uglify-js");
    2. var code = {
    3.     "file1.js": "var obj={foo:'\u4e11',zdd:20};obj.foo+=10;",
    4. };
    5. var result = UglifyJS.minify(code, {
    6.         output: {
    7.     ascii_only: true,
    8.         }
    9. });
    10. console.log(result.code);
    11. /*
    12. 结果:
    13. var obj={foo:"\u4e11",zdd:20};obj.foo+=10;
    14. */

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

    comments

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

    回到顶部
    我要评论

    所有评论

      相关文章