今天主要分享几点性能优化的实用方案,在前几个月在公司实习的时候,经过回顾作的一些实战项目总结出来了的,这对于刚刚接触到前端性能问题的童鞋,但愿可以给你提供一些入门型的指导。css
谈起性能优化这个话题,实在是太大的,不只仅只是前端的性能优化,也是全链路的性能优化。前端、后台、服务器、网络等各个模块的配合。前端
我在搞性能优化中,有些有关性能优化的点是《前端性能优化》的做者阿里的修言老哥给我稍做指点,加上实战中的应用和反馈总结,才让我得以有所感悟,值的去写一写。算法
今天所分享到的性能优化这个范围也是根据我以前公司所在的一些业务和所使用的技术栈来展开聊聊的。有具体的优化场景,咱们再谈起性能优化才以为更加有意思。后端
面临的技术栈和场景浏览器
若是不是对技术栈要求特别严格的公司来讲,前端开发少不了这几个技术栈。HTML5 + CSS3 + jQuery,有些公司还在用 JSP、.Net开发,针对这写传统技术,咱们须要使用一些特殊的手段去作优化。缓存
脱离了像 Vue 这种自己就是放弃传统操做 DOM 的框架,只针对于传统的性能优化,咱们如何下手?性能优化
PS:本文不谈太过关于框架性能优化的内容,只从传统的性能优化点出发。服务器
从定位问题开始网络
有一次,线上项目出现问题,页面某一部分渲染须要很长时间才显示,究竟是哪出了问题。app
定位问题,是什么致使了该页面部份内容加载过慢,是数据的获取过程,仍是页面 JS 加载过程,仍是其余渲染、绘制过程?
经过浏览器控制台的俗称神器的 Performance 定位问题。
这里我以某网站为项目对象,作个示范。
那个部分用时比较长,经过这个图能够分析到是哪一个环节出现了渲染时间比较长。
定位问题以后,开始作优化。可是作优化前提是具体一些优化的基础内容,否则咱们根本不知道从哪里着手开始优化。
数据请求时间过长
有时候咱们在作项目时,数据量太大,从服务器拿到数据这个过程时间太长。要想将这个时间变短,咱们须要减小请求的次数以及单次请求的时间。
对于减小请求次数,咱们能一次获取的尽可能一次获取到数据,而不是分为屡次去请求,若是请求过多就会形成线程的阻塞。
咱们能够结合具体业务进行适当的优化,将一些返回的【数据合并】,从而达到减小请求次数的目的。
可是单次请求的时间过长也是耗时间的,咱们传输大量的数据,只能将这些数据作压缩处理,这样单次请求就会变快。
还有其余一些方案,好比懒加载,页面给用户呈现哪部份内容,就请求哪部份内容,而不是一股子气所有请求回来。再好比,音频走的是流文件,而不是把整段音频请求回来才给用户播放,而是以流水的形式,边播放,边请求。
避免发生重绘和回流
除此以外,最关键的就是页面中的优化。首先回顾一下浏览器的工做原理。
动画: 一个浏览器是如何工做的?
其中一个环节是渲染环节,将合成的渲染树经过计算得出的像素位置和样式,渲染到页面中,最后呈献给用户。
虽然咱们在浏览器看到的页面没有感受,可是这个过程很是耗时的,尤为是当咱们稍微改动页面某一个元素的位置大小或者样式的时候,都会致使整个页面从新进行渲染。
若是页面要渲染的内容不少,用户每改动一个地方,就会形成所有渲染,性能很是耗时,最后致使用体验很差,严重状况形成页面无响应。
咱们看到的不少文章中提到,咱们应该尽可能的避免频繁的操做 DOM,从而避免发生页面的回流和重绘。
咱们发现 Vue 作了哪些改进,既然操做 DOM 致使性能不好,我就不操做 DOM 呗,因此 Vue 放弃了传统的 DOM 操做,开启了数据影响视图模式。(PS:后期在分析 Vue 源码文章中,我会主要分享这部分它内部如何巧妙实现的,而后带你们本身手写一个简易版的 Vue)
可是很无奈,有些公司不用 Vue,这样的公司太多了,领导表示就是不想用。就是想用传统的 HTML5 + CSS3 + jQuery,那么咱们对于优化又该怎么作?
我我的又根据,作了一些性能优化总结。既然不让用 Vue,那就决定的特定场景仍是涉及到操做 DOM 咯,虽然不能放弃传统 DOM,那么,我尽可能的减小操做 DOM 行不行,没错,按照这个方向去想,咱们能够总结出如下几点内容,小本本划重点。
一、
分离读写操做
咱们频繁的改变页面样式的位置以及大小会致使页面的回流和重绘,当代浏览器对这一点作了一点优化,当前行代码若是改变了元素大小或者位置,不会当即致使页面从新渲染,并且判断下一行是否也是改变元素大小和样式。
div.style.background = '#fff' div.style.color = 'red'
若是是,这些连续的代码将阿计入到一个渲染队列当中去,直到下一行代码不是改变样式的代码,而后统一作一次页面渲染,这样大大减小了页面的回流和重绘。
咱们根据这个浏览器渲染队列机制,咱们在写代码的时候,将读写属性操做作分离,像下面这样。
var curLeft = div.offsetLeft; var curTop = div.offsetTop ; div.style.left = curLeft + 1 + 'px' div.style.top = curTop + 1 + 'px'
若是不分离读写操做,而是将读写操做混起来写,这样会致使不断的回流和重绘。
二、
样式集中改变
同理,在咱们用 JS 批量改变样式的时候,要进行集中改变样式。
box.style.cssText = 'width:200px;height:200px'; box.className = 'aa'
三、
缓存布局信息
咱们一般会经过 JS 动态布局的大小,咱们一般会这样作。
// 如下会引起两次回流 div.style.left = div.offsetLeft + 1 + 'px' div.style.top= div.offsetTop + 1 + 'px'
可是按照咱们上边所总结的,这样子作很差,由于会致使屡次重绘。
若是咱们这样,先把获取的布局信息经过变量进行缓存,而后再统一改变样式。
// 修改成:只会触发一次回流 var curLeft = div.offsetLeft; var curTop = div.offsetTop ; div.style.left = curLeft + 1 + 'px' div.style.top = curTop + 1 + 'px'
四、
元素批量修改
若是咱们进行批量的改变元素,咱们能够单独拿出来改变完,而后再放回页面中,这样,你不管改变多少次,只引起一次回流。
// 文档碎片 let frg = document.createDocumentFragment(); for(let i = 0;i < 5;i++){ let newLi = document.createElement('li'); newLi.innerHTML = i; frg.appendChild(newLi); }
除此以外,咱们也可使用字符窗拼接的方式。
// 字符串拼接 for(let i= 0;i< 5;i++){ str += `<li>${i}</li>` } box.innerHTML = str
五、
动画优化
有时候咱们想使用动画,动画会频繁的改变元素的状态,致使不断的回流和重绘。
因此咱们为了可以使性能更佳,咱们动画效果应用到 position 属性为 absolute 或 fixed 上(脱离文档流)。
虽然会在一个新的平面,也会引起回流,可是不会影响到其余的元素,这样看起来性能更好。
六、
开启 CSS 硬件加速(GPU加速)
CSS3 改变样式能用 transform 的局部用其余元素,由于 transform 开启了硬件加速,规避了【回流】和【重绘】。
box.style.transform = 'translateX(200px)'
硬件加速的其余属性:transform \ opacity \ filters。因此能用这些属性尽可能用这些属性去改变元素。
七、
牺牲平滑速度换取速度
每次动画移动一个像素,CPU 占用率 100%,动画看起来有些跳动,由于浏览器正在与回流做斗争。
若是每次移动 3 像素可能看起来平滑度下降了,可是不会致使 CPU 在较慢的机器中抖动。
小结
以上是对于一些传统网页存在的性能问题,总结的几点优化方案。可是只靠这几点仍是远远不够的。
开篇提到过,性能优化不只仅是前端或者是后端工程师的事情,并且全链路的性能优化。
不管是性能优化仍是算法、网络等其余方面,都应该造成一种属于本身的思想知识体系。经过不断的遇到问题,解决问题,而后不断完善这个体系,这才是咱们最终要追求的一个小目标。