随着前端的发展,尤其是React、Vue等单页应用的兴起,前端的能力有了很大的提升,项目的开发也随之复杂化。这个时候前端的静态资源越来越大,毫无疑问javascript资源是前端的主要资源,压缩它的大小非常重要。为什么更小的尺寸很重要:更小的尺寸意味着更快的加载速度和更好的用户体验,这也可以为企业带来更大的利润。此外,更小的尺寸意味着更少的带宽和更少的服务器服务器成本。前端构建编译代码时,可以使用webpack中的optimization.minimizer对代码进行压缩优化。但是我们也需要了解它是如何压缩代码的,这样我们在生产环境的控制台调试代码的时候才能对它有更深入的了解。如何查看资源的大小对于我们写的代码来说,它是操作系统中的一个文件,我们可以根据文件系统中的stat信息来查看文件的大小。stat命令用于打印文件系统信息:$statconfig.jsFile:'config.js'Size:3663Blocks:8IOBlock:4096regularfileDevice:fd01h/64769dInode:806060Links:1Access:(0644/-rw-r--r--)Uid:(0/root)Gid:(0/root)Access:2020-02-1313:43:54.851381702+0800Modify:2020-02-1313:43:52.668417641+0800Change:2020-02-1313:43:52.691417262+0800Birth:-stat打印的信息太大,如果只是用来测量体积,可以使用wc-c。$wc-cconfig.js3663config.js是如何压缩代码大小的?去除多余的字符:空格、换行和注释//两个数的求和functionsum(a,b){returna+b;}首先把一个抽象的问题具体化,如果是上面的代码,如何压缩大小呢:此时文件大小为62Byte,一般中文会占用较多空间。多余的空白字符会占用很大的体积,比如空格、换行符、注释等也会占用文件体积。当我们删除所有空格和注释时,代码大小将会减少。删除多余字符后,文件大小变为30Byte。压缩后的代码如下:functionsum(a,b){returna+b}替换多余字符后会出现什么问题?是的,比如把多行代码压缩成一行的时候要注意行尾的分号。这需要通过下面描述的AST来解决。压缩后的变量名:变量名、函数名和属性名functionsum(first,second){returnfirst+second;}如上,first和second在函数作用域内,在作用域外不会被引用。这时候,他们的变量名就更短了。但是如果这是一个模块,sum函数不会被导出?这也可以缩短函数名称。//Compress:Shortenthevariablenamefunctionsum(x,y){returnx+y;}//Recompress:removeblankcharactersfunctions(x,y){returna+b}在这个例子中,当代码被压缩(compress)的时候,代码混淆(mangle)也是顺带做的。但此时缩短变量的命名也需要AST的支持,以免造成作用域的命名冲突。更简单的表达式:合并语句和简化布尔语句的示例如下://压缩前consta=3;constb=4;//压缩后consta=3,b=4;一个boolean化简的例子如下:://Beforecompression!b&&!c&&!d&&!e//Aftercompressionb||c||d||e这个例子需要解析AST。ASTAST,抽象语法树,js代码解析后的最小词法单元,这个过程是通过Parser完成的。那么AST能做什么呢?eslint:验证你的代码风格babel:将代码编译成ES低版本taro/mpvue:各种可以在多终端上运行的小程序框架GraphQL:解析客户端查询我们在日常工作中经常会不经意地处理它,比如eslint和babel,它会涉及在js和代码中徘徊。不同的解析器会生成不同的AST。常见的是使用babel使用的解析器babylon,而uglify在代码压缩中使用的解析器是UglifyJS。在ASTExplorer[3]中可以直观感受一下,如下图所示:压缩代码的过程:code->AST->(transform)asmallerAST->code,和巴别塔和埃斯林特。UglifyJS不要重新发明轮子!于是找了一个比较有名的代码压缩库:UglifyJS3[4],一个代码压缩和混淆的库。那么它是如何进行一些压缩功能的,比如替换空白字符,答案是AST。webpack内置的代码压缩插件使用它,其工作流程大致如下://原始代码constcode=`consta=3;`//UglifyJS将代码解析成ASTconstast=UglifyJS.parse(code);AST。figure_out_scope();//转换成更小的AST树compressor=UglifyJS.Compressor();astast=ast.transform(compressor);//将AST转换成代码code=ast.print_to_string();而当你真正使用它来压缩代码时,你只需要编程进行配置。文档请参考uglify[5]的官方文档。{{ecma:8,},compress:{ecma:5,warnings:false,comparisons:false,inline:2,},output:{ecma:5,comments:false,ascii_only:true,}}在webpack代码中压缩知道了代码压缩是怎么做的之后,我们终于可以把它搬到生产环境中来压缩代码了。终于到了练习的时候了,虽然只是简单的调用API和调整参数。与性能优化相关的一切都可以在优化中找到,TerserPlugin是一个基于uglifyjs的低级JS压缩插件。优化:{minimize:isEnvProduction,minimizer:[newTerserPlugin({terserOptions:{parse:{ecma:8,},compress:{ecma:5,warnings:false,comparisons:false,inline:2,},output:{ecma:5,评论:false,ascii_only:true,},},sourceMap:true})]}
