这是山月关于高级前端进阶暨前端工程系列文章的第 M 篇文章 (M 随便打的,毕竟也不知道能写多少篇),关于前 M-1 篇文章,能够从个人 github repo shfshanyue/blog 中找到,若是点进去的话能够捎带~点个赞~,若是没有点进去的话,那就给这篇文章点个赞。。今天的文章开始了javascript
本篇文章地址在 前端工程化系列,欢迎订阅。前端
随着前端的发展,特别是 React
,Vue
等构造单页应用的兴起,前端的能力得以很大提高,随之而来的是项目的复杂度愈来愈大。此时的前端的静态资源也愈来愈庞大,而毫无疑问 javascript
资源已经是前端的主体资源,对于压缩它的体积至为重要。vue
为何说更小的体积很重要呢:更小的体积对于用户体验来讲意味着更快的加载速度以及更好的用户体验,这也能早就企业更大的利润。另外,更小的体积对于服务器来讲也意味更小的带宽以及更少的服务器费用。java
前端构建编译代码时,可使用 webpack
中的 optimization.minimizer
来对代码进行压缩优化。可是咱们也须要了解如何它是压缩代码的,这样当在生产环境的控制台调试代码时对它也有更深入的理解。node
对于咱们所编写的代码,它在操做系统中是一个文件,根据文件系统中的 stat
信息咱们能够查看该文件的大小。webpack
stat
命令用来打印文件系统的信息:git
$ stat config.js File: ‘config.js’ Size: 3663 Blocks: 8 IO Block: 4096 regular file Device: fd01h/64769d Inode: 806060 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2020-02-13 13:43:54.851381702 +0800 Modify: 2020-02-13 13:43:52.668417641 +0800 Change: 2020-02-13 13:43:52.691417262 +0800 Birth: -
stat
打印的信息过大,若是只用来衡量体积,可使用 wc -c
github
$ wc -c config.js 3663 config.js
// 对两个数求和 function sum (a, b) { return a + b; }
先把一个抽象的问题给具体化,若是是以上一段代码,那如何压缩它的体积呢:web
此时文件大小是 62 Byte
, 通常来讲中文会占用更大的空间。面试
多余的空白字符会占用大量的体积,如空格,换行符,另外注释也会占用文件体积。当咱们把全部的空白符合注释都去掉以后,代码体积会获得减小。
去掉多余字符以后,文件大小已经变为 30 Byte
。 压缩后代码以下:
function sum(a,b){return a+b}
替换掉多余字符后会有什么问题产生呢?
有,好比多行代码压缩到一行时要注意行尾分号。 这就须要经过如下介绍的 AST 来解决。
function sum (first, second) { return first + second; }
如以上 first
与 second
在函数的做用域中,在做用域外不会引用它,此时可让它们的变量名称更短。可是若是这是一个 module
中,sum
这个函数也不会被导出呢?那能够把这个函数名也缩短。
// 压缩: 缩短变量名 function sum (x, y) { return x + y; } // 再压缩: 去除空余字符 function s(x,y){return a+b}
在这个示例中,当完成代码压缩 (compress
) 时,代码的混淆 (mangle
) 也捎带完成。 但此时缩短变量的命名也须要 AST 支持,不至于在做用域中形成命名冲突。
合并声明的示例以下:
// 压缩前 const a = 3; const b = 4; // 压缩后 const a = 3, b = 4;
布尔值简化的示例以下:
// 压缩前 !b && !c && !d && !e // 压缩后 b||c||d||e
这个示例更是须要解析 AST 了
AST
,抽象语法树,js 代码解析后的最小词法单元,而这个过程就是经过 Parser 来完成的。
那么 AST 能够作什么呢?
咱们在平常工做中常常会不经意间与它打交道,如 eslint
与 babel
,都会涉及到 js
与代码中游走。不一样的解析器会生成不一样的 AST,司空见惯的是 babel 使用的解析器 babylon
,而 uglify
在代码压缩中使用到的解析器是 UglifyJS
。
你能够在 AST Explorer 中直观感觉到,以下图:
那压缩代码的过程:code -> AST -> (transform)一颗更小的AST -> code,这与 babel
和 eslint
的流程如出一辙。
不要重复造轮子!
因而我找了一个久负盛名的关于代码压缩的库: UglifyJS3,一个用以代码压缩混淆的库。那它是如何完成一些压缩功能的,好比替换空白符,答案是 AST。
webpack
中内置的代码压缩插件就是使用了它,它的工做流程大体以下:
// 原始代码 const code = `const a = 3;` // 经过 UglifyJS 把代码解析为 AST const ast = UglifyJS.parse(code); ast.figure_out_scope(); // 转化为一颗更小的 AST 树 compressor = UglifyJS.Compressor(); ast = ast.transform(compressor); // 再把 AST 转化为代码 code = ast.print_to_string();
而当你真正使用它来压缩代码时,你只须要面向配置编程便可,文档参考 uglify 官方文档
{ { ecma: 8, }, compress: { ecma: 5, warnings: false, comparisons: false, inline: 2, }, output: { ecma: 5, comments: false, ascii_only: true, } }
在知道代码压缩是怎么完成的以后,咱们终于能够把它搬到生产环境中去压缩代码。终于到了实践的时候了,虽然它只是简单的调用 API 而且调调参数。
一切与性能优化相关的均可以在 optimization
中找到,TerserPlugin
是一个底层基于 uglifyjs
的用来压缩 JS 的插件。
optimization: { minimize: isEnvProduction, minimizer: [ new TerserPlugin({ terserOptions: { parse: { ecma: 8, }, compress: { ecma: 5, warnings: false, comparisons: false, inline: 2, }, output: { ecma: 5, comments: false, ascii_only: true, }, }, sourceMap: true }) ] }
扫码添加个人机器人微信,将会自动(自动拉人程序正在研发中)把你拉入前端高级进阶学习群
我是山月,能够加我微信
shanyue94
与我交流,备注交流。另外能够关注个人公众号【全栈成长之路】