内容来源:2017年7月15日,前端框架《Vue.JS》做者尤雨溪在“2017 JavaScript中国开发者大会”进行《前端工程中的编译时优化》演讲分享。IT 大咖说(微信id:itdakashuo)做为独家视频合做方,经主办方和讲者审阅受权发布。
javascript
阅读字数:1876 | 6分钟阅读前端
嘉宾演讲视频及PPT回顾:suo.im/4TcEw
java
经过对压缩器、打包工具,以及模板引擎处理的讲解,来更深刻的理解编译时优化是如何做用的。同时详细介绍了Vue是如何处理编译时优化的。以及将来前端领域在编译时上能作出那些更出色的优化。数组
在一段时间以前前端是没有编译这回事的,大部分人都是打开一个页面就开始写。可是随着前端愈来愈复杂,开发前端时新增的部分愈来愈多,NodeJs、Webpack、BABEl等变得必不可少,同时Css也要进行预处理。到了如今编译已经成了前端开发中不可或缺的一环。浏览器
编译是一个语言到另外一个语言表达的转变,这里面不只仅是功能上的应用,好比说从ES6转化到ES5,还能够给程序带来性能上的优化。前端框架
目前全部的编译器都是先将源代码Parser成AST(抽象语法树),而后对AST进行分析,在这个分析过程当中进行各类优化。微信
代码压缩其实就是一个构建时优化,咱们一般使用的压缩器就至关于编译器,它将原生的代码压缩成更简洁、更轻量的形式。常见的压缩器有Closuer Compiler、UglifyJS、Babili、Butternut。这里面UglifyJS不只仅是一个压缩器,它本身还实现了一套JS Parser,拥有一套代码生成系统,等因而构建了一个完整的编译工具链。Babili则是基于BABEL的插件实现的。框架
由此咱们能够从一直使用的压缩器中感觉到编译时优化是怎么样的一个做用过程。函数
早先的代码维护是很是不方便的,因此就出现一些打包工具,倡导开发者使用模块,使得代码可以更好的维护。可是另外一个问题出现了,打包后代码变得难以压缩。这是由于早期的打包工具每个模块都是包含在一个函数做用域内的,对于压缩器来讲每个做用域都是分离的,在进行优化的时候不少部分都没法完成。工具
针对上面的问题Rollup这类的工具就诞生了,只要是使用了ES模块,它就可让全部的模块都放在同一个做用域中,这样压缩器就有用武之地。
在使用模板引擎的时候,一般都会将模板直接写在JavaScript里面,模板字符串会被编译成JavaScript代码,这个过程通常都是在浏览器上进行的,可是这样就会增长用户的等待时间。
其实这个编译的过程彻底能够放在构建时进行,由此AOT和JIT出现了。JIT在构建时并不编译而是直接将模板发送到浏览器里,当须要使用的时候再进行编译。AOT则是在构建的时候提早进行编译。
Angular、Vue、Glimmer就是一个典型构建时编译的例子,编写的时候是模板而当编译完成后发送出去的倒是JavaScript代码。Angular使用AOT达成这一目标,Vue在使用Vue-loader时候默认就是这样执行的。
在生成Vue的渲染函数的时候,直接将静态元素存在一个数组里面,而后经过 return this._renderStatic(0) 来永远返回同一个片断,一样也能够跳过比对的过程。
对于Vue的template模板中的静态class,在生成代码中会做为staticClass出现。
在服务端渲染的时候,Virtual DOM是比不上字符串模板的。Vue会分析模板找出能够被拼接成字符串的部分直接进行拼接,而不能拼接的部分仍是使用Virtual DOM。这样就可使服务端渲染得到性能提高。
单页应用的包有时候会很大,整个下载下来的话对用户来讲性能上是不友好的。理想状况应该是在访问某个单页应用的时候只下载所访问的页面的JavaScript代码,要实现这样的效果就须要将代码切分红块。
Webpack的code-split功能就能够达到这一目标,由此咱们就会得到多个javascript文件。因为全部的关联信息都是在main.js里面,只有先加载main.js后才会知道后续要加载是哪一个js文件,这就形成了在服务端渲染的时候会有一次额外的加载,并形成延时。
在Vue的SSR里面客户端和服务端分别会有一次渲染。在客户端渲染的时候除了生成分割开的代码块以外,还会生成一个信息文件,包含了此次构建的这些模块对应的信息。而服务端的渲染会生成一个Server Bundle.js以及一样的信息文件。这样Vue在build以后就会得到服务端构建和客服端构建的关联信息,经过分析就能够在服务端得到一个请求的时候去计算出客户端应该须要的是哪些文件,而不须要去先加载main.js。
通常来讲服务端渲染中Css是须要提早加载的,不然的话页面是没有样式的。可是因为Css的文件较大,提早加载的话用户等待时间就会变长。解决方案就是提早加载一些关键的Css,要达到这一目的就须要在编译时提取这些Css。
而在Vue的单文件组件中Style部分会被抽取出来,于生成的JavaScript内是以动态的形式在该组件的生命周期钩子里去进行注入,也就是说在服务端渲染的时候只有用到的组件的Css样式才会被加载。
在编译时分析Vue的全部组件的源码,来找出那些功能没有用到,而后将Vue源码内这些用不到的部分去除掉,这样就能够更进一步的精简代码生成量。