一次性弄懂性能优化
最后更新于
这有帮助吗?
最后更新于
这有帮助吗?
若愚老师的版本
前端性能优化是面试官常考的问题,这道题可以从不同角度考察面试者的前端功底。如只能答出三四条如资源的打包合并明显是不足以通过面试的。面试的时候如果仅仅只是罗列网上的文章也是不行的,因为听上去会非常松散,因此也切忌死记硬背前端性能优化的问题。
若愚老师提供了两个思路可以着手去回答。
第一个思路是从日常接触到的前端性能场景出发。
性能瓶颈主要出现在三个场景
在开发时每次修改代码打包需要几分钟,太慢(开发构建阶段)
打开网站,等了几十秒才看到页面,太慢(资源加载和页面渲染阶段)
页面展现后,页面上动画不流畅。滚动页面或者拖拽元素卡顿感严重,甚至页面会崩溃(操作体验阶段)
可以通过前端开发的不同阶段来一一举例回答问题。
开发构建阶段
资源加载阶段
页面渲染阶段
操作体验阶段
资源下载越小越好,或者说体积越小加载越快,那么就涉及资源打包合并,以及服务器端开gzip(合并资源的前提下又压缩了文件)。
距离离得近,比如静态资源(CSS,JS,图片)放CDN,图片也要压缩。
以前会用sprite图,将所有图片合并成一张,然后通过坐标来获得相应的图片,但是这种方法已经很少使用了。
目前图标都是使用SVG图标,可以合并压缩SVG图标。
懒加载/异步加载,懒加载在什么时候使用?比如对应的模块如果还没有在网页上显示先不要加载。还有图片懒加载,
假设只使用了一个库里的一个函数,打包的时候可以用webpack的treeshake。
HTTP的缓存,比如有些资源不用每次都去请求。
使用HTTP2,类似于你的运输工具更先进,那么资源运输就会更加快和安全。
HTTP1的缺点就是不能多路复用,TCP/IP 三次握手。
HTTP2 优点就是可以多路复用(大公司面试会问到), 还有二进制分帧(HTTP1传输到信息都是字符串,比如header和body,HTTP2的传输是将数据进行二进制的分解,就像一帧一帧的画面,速度会更加快),头部压缩(相较于HTTP1,header被压缩),服务端推送(一次请求就可以拿到所有数据,不需要来来回回请求,但是需要浏览器支持HTTP2,当然大部分的浏览器都是支持HTTP2的)。
CSS在上(放在head里),JS在下。因为JS加载完了就会立即执行。当我们需要用户先看到页面,然后再和页面互动的时候,就需要JS慢点执行。
不重要的资源,比如第三方的统计代码,广告代码,因为他们不是很重要,所以可以加载慢点,可以使用async或者defer来异步加载。
比如说打开一个页面,有动画的动画不流畅,页面卡顿这些问题。
1. 尽量使用CSS3 animation。 CSS3能使用的动画效果,尽量不要使用js去做。CSS3的动画是通过GPU来渲染动画,如果是js的话会使用CPU。这样做的好处是不会干扰正常CPU中的线程,否则一旦出现互相干扰,就会造成动画不连贯。
2. 动画中的动作尽量使用transform
或者translate
,少用绝对定位如left/top。因为transform/translate
会开启硬件加速,也就是使用的是你的显卡GPU来渲染效果,从而减轻你CPU的负担。并且GPU的渲染速度要比CPU速度快。
3. JS动画少用setInterval
(因为动画会不连续,而且还会卡),而使用requestAnimationFrame,
DOM的增删操作要少(虚拟长列表,DOM Diff)。虚拟长列表(面试常考问题,比如如果有1万条数据需要渲染到页面上,用户在页面上滚动的时候,如何不卡顿,可以在页面上固定10个dom,用户每次滚动替换上面的内容,让用户觉得页面在滚动,实际上没滚)
高频操作要使用防抖和节流(比如有一个时间绑定在scroll上,每执行一次需要几百毫秒,那滚动几次页面就会出现卡顿)
对数据加密,对音频解析,因为计算需要用到CPU,因此页面也会出现卡顿,这种情况可以使用WebWorker(类似于自己开了一个新的线程,这个线程只做一件事情,当做好了之后再反馈给我们,和当前页面就没有任何关系和影响了)
以下针对webpack打包。
并发构建。可以使用插件来开启多进程来打包。
过滤不相关目录。使用loader的时候,需要查看文件,如果某个目录里有上万个文件,查找就会很慢,我们可以过滤这些目录,这些查找模块就会快一点。
使用缓存。使用loader的时候,可以使用缓存,这样速度会快。
凡是涉及到性能优化,脑子里一定要有两个词,一个是并发,另一个是缓存,优化方法有很多,但是这两个词在不同阶段都能用得到。