美文网首页
性能专题-前端性能提升诀窍!

性能专题-前端性能提升诀窍!

作者: WXL_JIANSHU | 来源:发表于2019-01-05 11:46 被阅读0次

    首先想问大家一个问题:假如现在有两个同样可以满足我们需求的网站,一个“Duang”的一下就加载出来了,一个纠结了半天才出来,你会选择使用哪一个?

    下面我们再来感受一下这张图片。

    image

    响应速度对用户的影响(用等待时间来衡量)

    从图中可以看出来:前端性能,反应给用户最直观的方面就是页面的响应速度。3-5秒还能接受,大于8秒甚至10秒以上的响应时间,作为用户肯定是接受不了的,相信我们自己平常上网逛论坛也有类似的体验。可以说页面的响应速度已经严重影响到了用户体验。

    其实有的时候,很多小的改变就可以让用户体验有质的提升。比如保持一个良好的编码习惯和一些简单但不太注意到的策略。接下来,我们就来研究一下,如何来提高页面的响应速度。

    1、避免坏请求

    什么是坏请求?最明显的就是404请求,也可以把无意义的重复请求叫做坏请求。无意义的请求,浪费了服务器的资源也影响前端性能。404会导致服务器无谓的响应,所以没用的请求,比如链接图片、请求无用的资源等都需要及时删除。

    image

    2、合并脚本文件和样式表:
    将多个样式表或者脚本文件合并到一个文件中,可以减少HTTP请求的数量从而缩短效应时间。

    image

    然而合并所有文件对许多人尤其是编写模块化代码的人来说是不能忍的,而且合并所有的样式文件或者脚本文件可能会导致在一个页面加载时加载了多于自己所需要的样式或者脚本,对于只访问该网站一个(或几个)页面的人来说反而增加了下载量,所以大家应该自己权衡利弊。

    3、添加Expires头

    页面的初次访问者会进行很多HTTP请求,但是通过使用一个长久的Expires头,可以使这些组件被缓存,下次访问的时候,就可以减少不必要的HTPP请求,从而提高加载速度。

    Web服务器通过Expires头告诉客户端可以使用一个组件的当前副本,直到指定的时间为止。例如:Expires: Fri, 18 Mar 2016 07:41:53 GMT

    Expires缺点是它要求服务器和客户端时钟严格同步;过期日期需要经常检查。HTTP1.1中引入Cache-Control来克服Expires头的限制,使用max-age指定组件被缓存多久。Cache-Control: max-age=12345600。若同时制定Cache-Control和Expires,则max-age将覆盖Expires头。

    4、使用CSS Sprites整合图片

    CSS Sprites直译过来就是CSS精灵,但是这种翻译显然是不够的,其实就是通过将多个图片融合到一副图里面,然后通过CSS的一些技术布局到网页上,这样就有效减少了请求次数。特别是图片特别多的网站,如果能用CSS Sprites降低图片数量,带来的将是速度的提升。

    <div>

    <span id="image1" class="nav"></span>

    <span id="image2" class="nav"></span>

    <span id="image3" class="nav"></span>

    <span id="image4" class="nav"></span>

    <span id="image5" class="nav"></span>

    </div>

    .nav {

    width: 50px;
    
    height: 50px;
    
    display: inline-block;
    
    border: 1px solid #000;
    
    background-image: url('E:/1.png');
    

    }

    image1 { background-position: 0 0; }

    image2 { background-position: -95px 0; }

    image3 { background-position: -185px 0; }

    image4 { background-position: -275px 0; }

    image5 { background-position: -366px -3px; }

    使用CSS Sprites还有可能降低下载量,可能大家会认为合并后的图片会比分离图片的总和要大,因为还有可能会附加空白区域。实际上,合并后的图片会比分离的图片总和要小,因为它降低了图片自身的开销,譬如颜色表、格式信息等。

    5、压缩组件

    从HTTP1.1开始,Web客户端可以通过HTTP请求中的Accept-Encoding头来表示对压缩的支持Accept-Encoding: gzip,deflate

    如果Web服务器看到请求中有这个头,就会使用客户端列出来的方法中的一种来进行压缩。Web服务器通过响应中的Content-Encoding来通知Web客户端。Content-Encoding: gzip

    6、优化脚本js和样式表css的顺序

    将样式表放在头部,将脚本放在底部。虽并不能造成太大影响,但是这会减少页面首屏出现的时间,使页面内容逐步呈现。改善用户体验,防止“白屏”。我们总是希望页面能够尽快显示内容,为用户提供可视化的回馈,这对网速慢的用户来说是很重要的。

    7、减少dom数量

    想方设法减少dom数量,即减少浏览器处理的时间,因为很多时候客户端javascript处理的就是dom,dom的多少直接影响前端到性能,而且是全方位多角度的影响。可以想象下,如果web应用程序中含有成千上万的dom节点,是比原本多很多的节点,这些节点数据都是ajax请求回来的。更要命的是,在这些节点下,还需要完成搜索的功能。然后我们需要使用选择器操作dom,无论如何优化,这些dom节点都是存在的,这无疑是一项耗时的工作。浏览器解析dom,渲染样式都会花费不少时间,何况还需要操作搜索和各种重绘。

    8、避免重定向

    --什么是重定向

    重定向用于将用户从一个URL重新路由到另一个URL。

    --常用重定向的类型

    301:永久重定向,主要用于当网站的域名发生变更之后,告诉搜索引擎域名已经变更了,应该把旧域名的的数据和链接数转移到新域名下,从而不会让网站的排名因域名变更而受到影响。

    302:临时重定向,主要实现post请求后告知浏览器转移到新的URL。

    304:Not Modified,主要用于当浏览器在其缓存中保留了组件的一个副本,同时组件已经过期了,这是浏览器就会生成一个条件GET请求,如果服务器的组件并没有修改过,则会返回304状态码,同时不携带主体,告知浏览器可以重用这个副本,减少响应大小。

    --重定向如何损伤性能

    当页面发生了重定向,就会延迟整个HTML文档的传输。在HTML文档到达之前,页面中不会呈现任何东西,也没有任何组件会被下载。

    9、使Ajax可缓存

    Ajax的目地是为了突破web本质的开始——停止的交互方式,向用户显示一个白屏后重绘整个页面不是一种好的用户体验。

    --异步与即时

    Ajax的一个明显的优点就是向用户提供了即时反馈,因为它异步的从后端web服务器请求信息。用户是否需要等待的关键因素在于Ajax请求是被动的还是主动的。被动请求是为了稍后使用而预先发起的,主动请求是基于用户当前的操作而发起的。

    --什么样的AJAX请求可以被缓存

    POST的请求,是不可以在客户端缓存的,每次请求都需要发送给服务器进行处理,每次都会返回状态码200。(可以在服务器端对数据进行缓存,以便提高处理速度)。

    GET的请求,是可以(而且默认)在客户端进行缓存的,除非指定了不同的地址,否则同一个地址的AJAX请求,不会重复在服务器执行,而是返回304。

    --Ajax请求使用缓存

    在进行Ajax请求的时候,可以选择尽量使用get方法,这样可以使用客户端的缓存,提高请求速度。

    10、使用浏览器文档碎片

    createDocumentFragment可以减少操作dom的次数,从而减少渲染次数,提高页面性能。下面我们来看个实例,看具体如何运用文档碎片来改善页面的性能。

    现在假设页面中有个列表ul元素,我们需要调用ajax获取json数据来填充这个列表。

    <u style="box-sizing: border-box;">第一个版本代码:</u>
    var list = document.querySelector('ul');
    ajaxData.items.forEach(function(item) {
    // 创建li元素
    var li = document.createElement('li');
    li.innerHTML = item.text;
    // li元素常规操作,例如添加class,更改属性attribute,添加事件监听等
    // 迅速将li元素注入父级ul中
    list.apppendChild(li);
    });
    这样的写法实际上是非常慢的,因为每一个元素附加到ul元素之上,顺带着浏览器处理渲染的过程。我们再来看看使用文档碎片的写法如何。

    <u style="box-sizing: border-box;">第二个版本代码:</u>
    var frag = document.createDocumentFragment();
    ajaxData.items.forEach(function(item) {
    // 创建li元素
    var li = document.createElement('li');
    li.innerHTML = item.text;
    // li元素常规操作
    // 例如添加class,更改属性attribute,添加事件监听,添加子节点等
    // 将li元素添加到碎片中
    frag.appendChild(li);
    });
    // 最后将所有的列表对象通过DocumentFragment集中注入DOM
    document.querySelector('ul').appendChild(frag);
    使用文档碎片处理之后,我们可以分析下附加节点到ul之上,只需一次就可以,大大减少了浏览器处理渲染的过程,节省了宝贵的时间。如果没有事件方面的考虑,或者可以使用事件委托的情况下,甚至可以把节点都当成html来处理,那么我们操作的就都是字符串了,请看第三个版本代码。

    <u style="box-sizing: border-box;">第三个版本代码:</u>
    var htmlStr = '';
    ajaxData.items.forEach(function(item) {
    // 构建包含HTML页面内容的字符串
    htmlStr += '<'+'li>' + item.text + '<'+'/li>';
    });
    // 通过innerHTML设定ul内容
    document.querySelector('ul').innerHTML = htmlStr;
    当然,如果觉得这样字符串太长,我们可以运用数组。

    <u style="box-sizing: border-box;">第四个版本代码:</u>
    var htmlStr = '';
    var htmlArr = [];
    ajaxData.items.forEach(function(item) {
    // 构建包含HTML页面内容的字符串
    htmlArr.push('<'+li>' + item.text + '<'+/li>');
    });
    // 通过innerHTML设定ul内容
    htmlStr = htmlArr.join('');
    document.querySelector('ul').innerHTML = htmlStr;

    总结

    按照以上总结,前端性能提升,我们有两张王牌:减少请求,加快渲染!

    我们从这两点出发,就可以解决很多问题。以上大都是总结出来的一些可用的细节点。实际上,我们也可以通过工具来检查页面上可供优化的地方,目前比较好用的工具是google page speed,使用方法也很简单。另外也可以参考page speed的说明,查找更多可供优化的信息。大家可以根据实际的项目需求以及遇到的问题,不断尝试,找到最适合的前端性能提升方案。
    毕竟,没有最快只有更快!

    相关文章

      网友评论

          本文标题:性能专题-前端性能提升诀窍!

          本文链接:https://www.haomeiwen.com/subject/vgsrrqtx.html