• 前端优化(原创)


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

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

    ①输入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合成图像,单独线程,更流畅,但耗内存)

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

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

    *前端加载优化:
    ·使用外联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进度条:将加载情况呈现给用户。


    *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或者float

    *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避免重复连接。
    ·等待响应:提高服务器运行速度——提高数据运算及查询速度。

  • 相关阅读:
    httpmodule httphandler
    多线程基础
    LiveRTMP之rtmp流flash播放器无法正常播放问题解决(二)
    LiveRTMP CPU占用问题调优(一)
    LiveRTMP之MP4文件进行rtmp点播直播推送(三)
    LiveRTMP推送RTSP视频源进行RTMP直播
    LiveRTMP Android采集AAC流进行RTMP推送
    LiveRTMP 简单高效的RTMP推送库
    mac 终端 常用命令
    Keychain保存数据封装
  • 原文地址:https://www.cnblogs.com/jacksplwxy/p/10948914.html
Copyright © 2020-2023  润新知