前端优化(原创)

前端优化只要在两方面进行,一是加载速度优化,二是渲染速度优化。在进行优化前,先掌握好2个基本理论知识css

 

理论知识(一):浏览器的完整加载渲染过程html

①输入url,发送请求
②加载(即下载)整个.html文件
③加载完后解析(即运行)html,并在解析的过程当中构建DOM树
·JavaScript是单线程的。浏览器是多线程的:有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面。
·浏览器按从上之下(深度遍历)的原则解析各个html标签
·解析标签的过程就是构建DOM树的过程
·解析遇到link、script、img标签时,浏览器会向服务器发送请求资源。
script加载时不影响其余资源加载,但因为不知道js中的执行内容,因此须要等JS加载并执行完后才会继续解析和渲染。
script的执行会阻塞html解析、其余下载线程以及渲染线程。
link加载完css后会解析为CSSOM(层叠样式表对象模型,一棵仅含有样式信息的树)。css的加载和解析不会阻塞html的解析,但会阻塞渲染。
img的加载不会阻塞html的解析,但img加载后并不渲染,它须要等待Render Tree生成完后才和Render Tree一块儿渲染出来。未下载完的图片需等下载完后才渲染。
④当css解析为CSSOM后,html解析为DOM后,二者将会结合在一块儿生成Render Tree(渲染树)。
⑤Layout(reflow): 计算出Render Tree每一个节点的形状和位置。(很耗性能)
⑥Painting(repaint):浏览器绘制这些元素的样式,颜色,背景,大小及边框等。(很耗性能)
⑦Composite(层叠时):浏览器会将各渲染层的信息发送给GPU,GPU会按照合理的顺序合并图层而后显示到屏幕上。(GPU合成图像,单独线程,更流畅,但耗内存)前端

 

理论知识(二):浏览器的渲染性能指标jquery

 大多数电脑显示器的刷新频率是60Hz,大概至关于每秒钟重绘60次,由于小于这个频率,页面的渲染就会出现卡顿现象,影响用户体验。大多数浏览器都会对重绘操做加以限制,不超过显示器的重绘频率,由于即便超过那个频率用户体验也不会有提高。所以,最平滑动画的最佳循环间隔是1000ms/60,约等于16.6ms。该指标是游戏开发中的最重要的指标。webpack

 

*前端加载优化:
·使用外联CSS和JS:让浏览器缓存,减小http请求。可利用webpack在引用的资源后面自动增长hash值,实现引用不变的基础上对浏览器缓存的资源进行更新。对于缓存容量小的问题,能够考虑缓存在localStorage。
·合并CSS、JS:减小http请求。
·按需加载:webpack的打包思路就是从程序逻辑入手:入口文件 => 分析代码 => 找出依赖 => 打包,这样代码里不引用的模块就不可能被打进包里,有效减小体积。
·按JS模块加载:例如echart中若是只用k线图就只加载k线模块。
·压缩HTML、CSS、JS:减小资源大小。
·图标采用base64:减小http请求。
·图标采用雪碧图(svg、font-icon):减小http请求,减小资源大小。
·图片压缩:picdiet(https://www.picdiet.com/zh-cn),是用JS编码,无大小、尺寸、数量限制,默承认平均减小50%体积,清晰度基本没损失,没有兼容性问题,也能够调节压缩比。
·避免图片和iFrame等的空src:减小http请求。
·图片:滚屏懒加载。
·CDN加速:经常使用资源使用CDN加速提升资源响应速度,如jquery、echarts。(http://www.bootcdn.cn/)
·BigRender首屏渲染优化:html, js, css和图片都放在textarea中懒加载(https://segmentfault.com/a/1190000006744741)。
·增长Loading进度条:将加载状况呈现给用户。web


*HTML、CSS结构优化:
·页面的标签越少,页面的加载速度就越快,响应也更加迅速。
·css不能阻塞加载,因此将css放在头部,防止白屏和重排重绘形成的内容闪烁现象。
·尽可能保持class的简短,如:.box:nth-last-child(-n+1) .title,改成:.final-box-title。
·用flex布局取代浮动布局。
·移除空的CSS规则:空的CSS规则增长了CSS文件的大小,且影响CSS树的执行。
·不声明过多的font-size:过多的font-size引起CSS树的效率。
·值为0时不须要任何单位:为了浏览器的兼容性和性能,值为0时不要带单位。
·display属性会影响页面的渲染,需合理使用:
①display:inline后不该该再使用width、height、margin、padding以及float
②display:inline-block后不该该再使用float
③display:block后不该该再使用vertical-align
④display:table-*后不该该再使用margin或者floatsegmentfault

*DOM性能优化:主要是防止重排和重绘
·图片、音频和视频的宽高在加载完成以前为0,因此静态资源加载前需规定图片的大小。
·尽可能避免重设图片大小:屡次重设图片大小会引起图片的屡次重绘
·多使用requestAnimationFrame(待学习)
·若是同时添加父元素和子元素,要在内存中先将因此子元素添加到父元素下,将父元素一次性加入DOM树。
·若是同时添加多个平级子元素,要先将平级子元素加入文档片断,再将文档片断总体加到页面。具体为:
①建立文档片断:var frag=document.createDocumentFragment();文档片断: 内存中临时存储多个平级子元素的虚拟父元素。
②将平级子元素,先追加到frag下: 用法同普通父元素
③将文档片断,总体添加到页面
·先把dom节点display:none;(会触发一次重排)。而后作大量的修改后,再把它显示出来。
·clone一个dom节点在内存里,修改以后;与在线的节点相替换。
·尽可能使用ID选择器,ID选择器是最快的。
·每次Dom选择都要计算,缓存他,避免强制同步布局(force reflow)。
·对于修改元素多个样式,可使用cssText属性,避免强制同步布局。例如以下,触发3次重排:
var el = document.getElementById('myDiv');
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
el.style.padding = '5px';
改为这样,只需1次重排:
var el = document.getElementById('myDiv');
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
将多个样式变化定义到一个class中,再经过className添加class也行。
·动画多使用transform和opacity,他们只会引发合成,不会引发布局和重绘。
·若是图层中某个元素须要重绘,那么整个图层都须要重绘。用translateZ(0)手动建立渲染层,减小需渲染的像素数,还能够用GPU加速。可是不要滥用这个属性,不然会大大增长内存消耗。(详情:https://developers.google.cn/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas)
·不要使用table布局,一个小改动会形成整个table的从新布局。
·用css动画而不是js动画:css动画有一个重要的特性,它是彻底工做在GPU上。由于你声明了一个动画如何开始和如何结束,浏览器会在动画开始前准备好全部须要的指令;并把它们发送给GPU。而若是使用js动画,浏览器必须计算每一帧的状态;为了保证平滑的动画,咱们必须在浏览器主线程计算新状态;把它们发送给GPU至少60次每秒。除了计算和发送数据比css动画要慢,主线程的负载也会影响动画; 当主线程的计算任务过多时,会形成动画的延迟、卡顿。因此尽量地使用基于css的动画,不只仅更快;也不会被大量的js计算所阻塞。
·减少复合层的尺寸:能够将图片的尺寸减小5%——10%,而后使用scale将它们放大;用户不会看到什么区别,可是你能够减小大量的存储空间。
·采用虚拟DOM技术:例如Vue、React等框架就采用了虚拟DOM。浏览器

*script优化:
·咱们知道脚本加载和运行会阻塞页面,因此应该把<script>标签放到最后。
·JS:throttle函数(节流):每XX秒内只执行一次;(https://segmentfault.com/a/1190000006722279)
·JS:debounce函数(防抖):当连续触发函数调用时,在最后一次触发的XX秒之后才开始一次调用。(https://segmentfault.com/a/1190000006732819)
·对于多条件判断,字典比if-else快。
·避免快速连续的布局:
改善前:function resizeWidth() {
// 会让浏览器陷入'读写读写'循环
for (var i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = box.offsetWidth + 'px';
}
}
改善后:var width = box.offsetWidth;
function resizeWidth() {
for (var i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = width + 'px';
}
}
·深刻原形链越深,搜索的速度就会越慢。记住,搜索实例成员的过程比访问直接量或者局部变量负担更重,因此增长遍历原形链的开销正好放大了这种效果。
·函数做用域链的搜索也会消耗性能,全局变量老是在做用域链的最后,因此耗时最久。最好尽量使用局部变量。一个好的经验法则是:用局部变量存储本地范围以外的变量值。
·成员嵌套越深,访问速度越慢。 location.href 老是快于window.location.href ,然后者也要比window.location.href.toString()更快。若是这些属性不是对象的实例属性,那么成员解析还要在每一个点上搜索原形链,这将须要更长时间。
·计算简化,如:for(var i=2;i<=Math.sqrt(n);i++){if(n%i==0){return false}}
·前面提到每帧的渲染应该在16ms内完成,但在动画过程当中,因为已经被占用了很多时间,因此JavaScript代码运行耗时应该控制在3-4毫秒。若是真的有特别耗时且不操做DOM元素的纯计算工做,能够考虑放到Web Workers中执行。缓存


*服务端设置优化:
·缓存一切可缓存的资源:http缓存。
·使用长Cache,避免304重定向:在移动端网络不稳定的前提下,多一次请求,就多了一部分加载时间。
·使用DNS缓存:减小浏览器会在DNS解析中消耗的时间。
·启用GZip:GZip是http协议的一部分,用来压缩网页大小的。
·图片压缩:默认生成缩略图传前端。
·减小Cookie:Cookie会影响加载速度,因此静态资源域名不使用Cookie。
·域名解析:减小域名解析次数——减小跨站外部资源的引用。
·建立链接:减小链接建立次数——使用Keep-Alive避免重复链接。
·等待响应:提升服务器运行速度——提升数据运算及查询速度。性能优化

相关文章
相关标签/搜索