当前位置:   article > 正文

前端性能优化(四)01-页面性能优化之优化原则——尽量减少HTTP请求 & 使用内容传送网络CDN & 避免空src或空href值 & 启用gzip压缩 & CSS放顶部,JS放底部& 减少DNS查找_gzip 占用 cpu

gzip 占用 cpu

前端性能优化(四)01-页面性能优化之优化原则——尽量减少HTTP请求 & 使用内容传送网络CDN & 避免空src或空href值 & 启用gzip压缩 & CSS放顶部,JS放底部& 减少DNS查找

优化原则

1、尽量减少HTTP请求

在浏览器(客户端)和服务器发生通信时,就已经消耗了大量的时间,尤其是在网络情况比较糟糕的时候,这个问题尤其的突出。

一个正常HTTP请求的流程简述:如在浏览器中输入"www.xxxxxx.com"并按下回车,浏览器再与这个URL指向的服务器建立连接,然后浏览器才能向服务器发送请求信息,服务器在接受到请求的信息后再返回相应的信息,浏览器接收到来自服务器的应答信息后,对这些数据解释执行。

而当我们请求的网页文件中有很多图片、CSS、JS甚至音乐等信息时,将会频繁的与服务器建立连接,与释放连接,这必定会造成资源的浪费,且每个HTTP请求都会对服务器和浏览器产生性能负担。

网速相同的条件下,下载一个100KB的图片比下载两个50KB的图片要耗费的网络资源更多。所以,请减少HTTP请求。

具体的方法:

  1. 组合文件,优化图片,使用sprites设计风格: 将背景图片合并成一个文件,通过background-imagebackground-position 控制显示;

    确保您的图像不大于它们所需的图像,它们采用正确的文件格式(PNG通常更适用于少于16种颜色的图形,而JPEG通常更适合照片)并且它们是针对Web压缩的。

    使用CSS sprites在网站上经常使用的图像创建模板,如按钮和图标。CSS sprites将您的图像组合成一个大图像,一次加载所有(这意味着更少的HTTP请求),然后只显示您想要显示的部分。这意味着您通过不让用户等待加载多个图像来节省加载时间。

    有一些在线工具:

  2. 肉联图片,使用data:URL方案将图像数据嵌入实际页面中。这可以增加HTML文档的大小。将内嵌图像组合到(缓存的)样式表中是一种减少HTTP请求并避免增加页面大小的方法。

  3. 简化页面的设计

2、使用内容传送网络CDN

内容分发网络(CDN),也称为内容传送网络,是用于分发传送内容的负载的服务器网络。从本质上讲,您网站的副本存储在多个地理位置不同的数据中心,以便用户可以更快,更可靠地访问您的网站。

对于初创公司和私人网站来说,CDN服务的成本可能过高,但随着您的目标受众变得越来越大并变得更加全球化,CDN对于实现快速响应时间是必要的。

请记住,最终用户响应时间的80-90%用于下载页面中的所有组件:图像,样式表,脚本,Flash等。这是Performance Golden Rule。而不是从重新设计应用程序架构的艰巨任务开始,最好首先分散您的静态内容。这不仅可以大大缩短响应时间,而且由于内容交付网络,它更容易实现。

内容传送网络(CDN)是分布在多个位置的Web服务器的集合,以更有效地向用户传送内容。选择用于向特定用户传送内容的服务器通常基于网络接近度的度量。例如,选择具有最少网络跳数的服务器或具有最快响应时间的服务器。

CDN服务商有很多,这里就不再多说:专门做CDN服务器的蓝讯、网宿、帝联、快网,还有阿里云、腾讯云、华为云等。国外如Akamai TechnologiesEdgeCastlevel3

除了去购买一些CDN服务商的服务以外,对于大多数开发者,可以使用公共CDN网络上的资源,如以下的方式去使用CDN加速:

<!-- google -->
<script
  type="text/javascript"
  src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"
></script>

<!-- cdnjs -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<!-- qiniu cloud -->
<script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>

<!-- other cdn -->
<script
  crossorigin="anonymous"
  integrity="sha384-vk5WoKIaW/vJyUAd9n/wmopsmNhiy+L2Z+SBxGYnUkunIxVxAv/UtMOhba/xskxh"
  src="https://lib.baomitu.com/jquery/3.4.1/jquery.min.js"
></script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
3、避免空src或者是href值

空的src和href都会导致多余的HTTP请求,虽然不影响加载时间,但是会对服务器产生不必要的流量和压力。浏览器仍然会向服务器发起一个 HTTP 请求:

  • IE 向页面所在的目录发送请求
  • Safari、Chrome、Firefox 向页面本身发送请求
  • Opera 不执行任何操作

空的src的image严重的以至于影响整个网站的用户体验,空 src 产生请求的后果不容小憩:

  • 给服务器造成意外的流量负担,尤其时日 PV 较大时;
  • 浪费服务器计算资源;
  • 可能产生报错。

有两种形式:

  1. HTML形式

    <img src="">
    <a href=""></a>
    
    • 1
    • 2
  2. JavaScript形式

    var img = new Image();
    img.src = "";
    
    • 1
    • 2

解决办法:

  1. 删除空的srchref标签
  2. a标签的href属性,连接到实际的页面:
<a href="#"></a>
<a href="#nogo"></a>
<a href="##"></a>
<a href="###"></a>
<a href="void(0);"></a>
<a href="void(0)"></a>
<a href=";"></a>
<a href=""></a>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. 禁止跳转,添加cursor:pointer样式
<style>
    a{cursor: pointer}
</style>
<a>点击一</a>
<a onclick="doSomething()">点击二</a>
  • 1
  • 2
  • 3
  • 4
  • 5
  1. a 标签创建一个带有描述信息的href 属性,并监控click事件调用preventDefault()函数。
<a href="#Something_De scriptive" id="my_id">Trigger</a>
<script>
    $("#my_id").click(function(e){
        e.preventDefault(); //取消单击事件的默认动作以阻止链接的跳转。
        //  其他的代码
})
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

优点:

  • <a>够响应键盘事件并获得焦点(从而屏幕阅读器能够读出背后的内容,增强可访问性)
  • 优雅降级,在网络连接很差,还没有加载到CSS的时候,<a>依然有手型与正常的link样式。
4、gzip的组件

所有现代浏览器都支持 gzip 压缩并会为所有 HTTP 请求自动协商此类压缩。启用 gzip 压缩可大幅缩减所传输的响应的大小(最多可缩减 90%),从而显著缩短下载相应资源所需的时间、减少客户端的流量消耗并加快网页的首次呈现速度。

从HTTP / 1.1开始,Web客户端表示支持使用HTTP请求中的Accept-Encoding标头进行压缩。

Accept-Encoding:gzip,deflate
  • 1

压缩包括XML和JSON在内的任何文本响应都是值得的。不应对图像和PDF文件进行gzip压缩,因为它们已经过压缩。试图对它们进行gzip不仅会浪费CPU,还可能会增加文件大小。

比如,在nginx中开启gzip压缩:

# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 2;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

其他web容器启动gzip的方法:

5、CSS放在顶部,JS放在底部

把Javascript脚本在底部,删除阻止渲染的JavaScript
在HTML文件<body>中指定外部样式表和内联样式块可能对浏览器的渲染性能产生不利影响。

  1. 浏览器阻塞渲染网页直到所有外部的样式表都已被下载。
  2. (用<style>标记指定的)内联样式块可能会导致reflows和页面跳动。
    因此,把外部样式表和内联样式块放在页面的<head>中是很重要的。通过确保样式表首先被下载和解析,可以让浏览器逐步渲染页面。

具体做法:

  • 将内联样式块和<link>元素从页面<body>移动到页面<head>中。

    HTML 4.01规范(第12.3节)规定,始终把使用<link>标签的外部样式表放在<head>部分里,还要确保您指定的样式有正确的顺序。

  • <style>区块放在<head>部分里。

  • 使用css媒体类型

如果可以让CSS资源只在特定条件下使用,这样这些资源就可以在首次加载时先不进行构建CSSOM树,只有在符合特定条件时,才会让浏览器进行阻塞渲染然后构建CSSOM树。

CSS的媒体查询正是用来实现这个功能的,它由媒体类型以及零个或多个检查特定媒体特征状况的表达式组成。

<!-- 没有使用媒体查询,这个css资源会阻塞渲染  -->
<link href="style.css"    rel="stylesheet">
<!-- all是默认类型,它和不设置媒体查询的效果是一样的 -->
<link href="style.css"    rel="stylesheet" media="all">
<!-- 动态媒体查询, 将在网页加载时计算。
根据网页加载时设备的方向,portrait.css 可能阻塞渲染,也可能不阻塞渲染。-->
<link href="portrait.css" rel="stylesheet" media="orientation:portrait">
<!-- 只在打印网页时应用,因此网页首次在浏览器中加载时,它不会阻塞渲染。 -->
<link href="print.css"    rel="stylesheet" media="print">
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用媒体查询可以让CSS资源不在首次加载中阻塞渲染,但不管是哪种CSS资源它们的下载请求都不会被忽略,浏览器仍然会先下载CSS文件。

把Javascript脚本在底部,删除阻止渲染的JavaScript

浏览器必须通过在呈现页面之前解析HTML来构建DOM树。如果您的浏览器在此过程中遇到脚本,则必须先停止并执行它,然后才能继续。

具体做法:

将脚本定义或引用放置到<body>底部。
<script defer="defer"> defer 属性规定是否对脚本执行进行延迟, 脚本将在页面完成解析时执行。

在这里插入图片描述

蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。

此图告诉我们以下几个要点:

  1. deferasync 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
  2. 它俩的差别在于脚本下载完之后何时执行,显然 defer*是最接近我们对于应用脚本加载和执行的要求的
  3. 关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用
  4. async 则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行
  5. 仔细想想,async对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics
6、减少DNS查找

用户访问网站的过程如下:

  1. 在地址栏输入网站地址,如www.example.com;

  2. 本地DNS得到这个请求,查询本地DNS缓存,如果有这条记录,则直接返回对应的IP;否则,请求网络上的DNS服务器,得到相应的IP,返回给客户机,并缓存这条记录;

  3. 浏览器向得到的IP发起建立连接请求,得到响应后建立连接,请求数据;

  4. Server端计算所需数据,并返回给client端;

  5. client端,即浏览器,解析数据并显示在浏览器窗口中,至此,请求完成。

在 一次请求中,DNS解析可以占到请求时间的三分之一左右(这点有待验证),所以如果可以缩短DNS解析时间,就可以加快页面的打开速度。

缩短DNS解析的 方法可以通过延长DNS缓存的时间选用更快的DNS Server减少域名总数(例如原来有5个img server,分别为img1.xxx.com至img5.xxx.com,则现在可以减少到3个)等等,但是减少域名个数又会降低资源并行下载的数量, 因为同一域名最多可以并行下载两个资源,所以这里需要一个折衷方案,作者的建议就是将资源分布在大于等于2但小于等于4个域名上(这个也有待验证,例如针 对多大的系统选用多少个域名是最合理的等)。

使用DNS预解析

这里会有一些兼容性问题,可以参见:http://caniuse.com/#feat=link-rel-dns-prefetch

在这里插入图片描述

在网页体验中我们常会遇到这种情况,即在调用百度联盟、谷歌联盟以及当前网页所在域名外的域名文件时会遇到请求延时非常严重的情况。那么有没有方法去解决这种请求严重延时的现象呢?

一般来说这种延时的原因不会是对方网站带宽或者负载的原因,那么到底是什么导致了这种情况呢。湛蓝试着进行推测,假设是DNS的问题,因为DNS解析速度很可能是造成资源延时的最大原因。在页面header中添加了以下代码(用以DNS预解析):

<meta http-equiv="x-dns-prefetch-control" content="on" />

<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
<link rel="dns-prefetch" href="http://nsclick.baidu.com" />
<link rel="dns-prefetch" href="http://hm.baidu.com" />
<link rel="dns-prefetch" href="http://eiv.baidu.com" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

dns-prefetch需慎用,多页面重复DNS预解析会增加重复DNS查询次数。

使用场景:

  1. 新用户访问,后端可以通过 Cookie 判断是否为首次进入站点,对于这类用户,DNS Prefetch 可以比较明显地提升访问速度
  2. 登录页,提前在页面上进行下一跳页用到资源的 DNS Prefetch
  3. 页面中的静态资源在不同的domain下,如CSS、JS、图片等文件
  4. 电商网站的商品页大量载入不同domain下的商品图,如淘宝
  5. 手机网页
  6. 大型网站
  7. js或服务端重定向

Chrome中的一些指令:

  • chrome://histograms/DNS.PrefetchQueue:查看队列状态
  • chrome://histograms/DNS:查看从浏览器启动到上一页的DNS记录
  • chrome://dns:查看个域名DNS统计
  • chrome://net-internals/#dns:清除host缓存
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/217790
推荐阅读
相关标签
  

闽ICP备14008679号