美文网首页
页面性能优化常用办法汇总

页面性能优化常用办法汇总

作者: HelloJames | 来源:发表于2018-11-22 21:48 被阅读69次

    前言

    互联网有一项闻名的8秒准绳。用户在访问Web网页时,若是时间超过8秒就会感应不不耐烦,若是加载时间太长,他们就会放弃访问。大部分用户希望网页能在2秒之内就完成加载。事实上,加载时间每多1秒,你就会流失7%的用户。8秒并不是切确的8秒钟,只是向网站开发者剖清楚明了加载时间的重要性。那我们应该如何优化页面性能,加快页面加载速度呢?本文只关注一些要点,以下是小编总结的几种常见的方法:

    资源压缩与合并

    主要包含以下几个方面:

    • html压缩
    • css压缩
    • js压缩和紊乱
    • 文件合并

    资源压缩可以从文件中去掉多余的字符, 比如回车和空格.

    1. html压缩

    html代码压缩就是压缩这些在文本文件中有意义,可是在HTML中不需要的字符,比如: 空格,制表符,换行符等,还有一些其他意义的字符,如HTML注释也可以被压缩。

    2. css代码压缩

    css代码压缩简单来说就是无效代码删除和css语义合并


    image.png

    3.js的压缩和紊乱

    如何进行js代码的压缩和紊乱呢?

    • 使用在线网站进行压缩
    • 使用html-minifier工具
    • 使用uglifyjs2对js进行压缩

    其实css压缩与js的压缩和紊乱比html压缩收益要大得多,同时css代码和js代码比html代码多得多。所以对大公司来说,html压缩无关紧要,但css压缩与js的压缩非常有必要!

    4. 文件合并

    将多个js/css小文件合并为一个文件, 减少网络请求数.

    非核心必要代码异步加载

    1. 异步加载

    实现异步加载有三种可行办法:

    • async
    • defer
    • 动态创建script标签

    async

    • async属性是HTML5新增属性, 目前在Chrome, Firefox, IE9+上支持.
    • async的设置,会使得script脚本异步的加载并在允许的情况下执行
    • async的执行,并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行。

    defer

    • 兼容所有浏览器
    • 如果script标签设置了该属性,则浏览器会异步的下载该文件并且不会影响到后续DOM的渲染;
    • 如果有多个设置了defer的script标签存在,则会按照顺序执行所有的script;
    • defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行。

    动态创建script标签

    在没有defer和async属性前, 异步加载是通过动态创建script标签, 在window.onload事件中触发动态创建script到dom中实现的.
    示例代码:

    function addScriptTag(src){
      var script = document.createElement('script');
      script.setAttribute("type","text/javascript");
      script.src = src;
      document.body.appendChild(script);
    }
    
    window.onload = function{
      addScriptTag("js/index.js");
    }
    

    2. defer&async异步加载的区别

    • defer是在HTML解析完之后才会实行,若是是多个,按照加载的依次实行
    • async是在加载完之后立即实行,若是是多个,实行按次和加载按次无关

    浏览器缓存

    对于web应用来说, 缓存是提升页面性能同时减少服务器压力的利器.

    浏览器缓存

    1. 强缓存

    不会向服务器发送请求, 直接从缓存中读取资源, 在Chrome控制台的network选项中可以看到该请求的状态码为200, 但size标识为from dist cache或者from memory cache.

    2. response header

    Expires

    response header里的过期时间, 浏览器再次加载该资源时, 如果在有效时间内, 则使用强缓存, 它的值是一个绝对时间(GMT时间字符串), 如: Expires:Thu,21 Jan 2018 23:39:02 GMT

    Cache-Control

    (1) 请求Request:

    • no-cache ---- 不要读取缓存中的文件,要求向WEB服务器重新请求
    • no-store ---- 请求和响应都禁止被缓存
    • max-age: ---- 表示当访问此网页后的max-age秒内再次访问不会去服务器请求,其功能与Expires类似,只是Expires是根据某个特定日期值做比较。一但缓存者自身的时间不准确.则结果可能就是错误的,而max-age,显然无此问题.。Max-age的优先级也是高于Expires的。
    • max-stale ---- 允许读取过期时间必须小于max-stale 值的缓存对象。
    • min-fresh ---- 接受其max-age生命期大于其当前时间 跟 min-fresh 值之和的缓存对象
    • only-if-cached ---- 告知缓存者,我希望内容来自缓存,我并不关心被缓存响应,是否是新鲜的.
    • no-transform ---- 告知代理,不要更改媒体类型,比如jpg,被你改成png.

    (2) 响应Response:

    • public ---- 数据内容皆被储存起来,就连有密码保护的网页也储存,安全性很低
    • private ---- 数据内容只能被储存到私有的cache,仅对某个用户有效,不能共享
    • no-cache ---- 可以缓存,但是只有在跟WEB服务器验证了其有效后,才能返回给客户端
    • no-store ---- 请求和响应都禁止被缓存
    • max-age: ----- 本响应包含的对象的过期时间
    • Must-revalidate ---- 如果缓存过期了,会再次和原来的服务器确定是否为最新数据,而不是和中间的proxy
    • max-stale ---- 允许读取过期时间必须小于max-stale 值的缓存对象。
    • proxy-revalidate ---- 与Must-revalidate类似,区别在于:proxy-revalidate要排除掉用户代理的缓存的。即其规则并不应用于用户代理的本地缓存上。
    • s-maxage ---- 与max-age的唯一区别是,s-maxage仅仅应用于共享缓存.而不应用于用户代理的本地缓存等针对单用户的缓存. 另外,s-maxage的优先级要高于max-age.
    • no-transform ---- 告知代理,不要更改媒体类型,比如jpg,被你改成png.
    Last-Modified 和 If-Modified-Since

    都是用于记录页面最后修改时间的 HTTP 头信息,注意:

    • Last-Modified 是由服务器往客户端发送的 HTTP
    • If-Modified-Since是由客户端往服务器发送的头

    再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。而且在一些ajax应用中,要求获取的数据永远是最新的,而不是读取位于缓存中的数据,做这样的设置是非常有必要的。


    image.png

    但Last-Modified存在一些缺点:

    • 有些服务器无法获取文件最新的修改时间
    • 文件的修改时间变了, 但内容可能没有变化

    既然按文件修改时间无法保证缓存是否合适, 那么是否可以考虑按文件内容来决定文件是否缓存呢?—-ETag和If-None-Match

    ETag 和 If-None-Match
    • ETag是上一次加载资源时, 服务器返回给浏览器客户端的response header, 是对该资源的一种唯一标识, 只要资源有变化, Etag就会重新生成, 浏览器每次加载资源向服务器发送请求时, 都会将文件上一次的Etag值放到request header的If-None-Match中, 服务器与客户端传入的If-None-Match进行比对, 看是否一致, 就能很好的断定资源是否有更新过. 若匹配, 则返回HTTP 304状态码, 浏览器则会直接使用本地缓存, 否则, 返回HTTP 200状态码, 返回最新的资源 .


      image.png

    Etag & Last-Modified 两者比较:

    • 从准确度来看, Etags要优于 Last-Modified, Last-Modified设置时间的最小单位是秒, 若某个文件在1秒内修改了两次或更多, Last-Modified无法精确的保证文件是否是最新的, 但Etag可以. 若是负载均衡服务器, 每个服务器生成的 Last-Modified值也可能不一致.
    • 从性能来看, Etag要逊于 Last-Modified, 因为 Last-Modified只需要设置时间即可, 而Etag则必须要服务器通过比对算法来比较hash值.
    • 从优先级来看, 服务器优先考虑校验Etag
    Cache-Control

    浏览器缓存机制流程图


    image.png

    CDN

    CDN服务提供商会有全国各个省份部署节点, 将网站静态资源部署到CDN后, 用户在访问页面时, CDN静态资源会从就近的CDN节点上加载资源. 当请求至达CDN节点后, 节点会判断资源是缓存是否有效, 若有效, 直接返回给用户, 若无效, 会从CDN服务器加载最新的资源返回给用户同时将资源保存一份到该CDN节点上, 以便后续的访问用户使用. 因此, 只在该地区有一个用户先加载了资源, 在CDN中建立了缓存, 该地区的其他用户都能受益.

    DNS预解析

    DNS 作为互联网的基础协议,其解析的速度似乎容易被网站优化人员忽视。现在大多数新浏览器已经针对DNS解析进行了优化,典型的一次DNS解析耗费20-120 毫秒,减少DNS解析时间和次数是个很好的优化方式。DNS Prefetching是具有此属性的域名不需要用户点击链接就在后台解析,而域名解析和内容载入是串行的网络操作,所以这个方式能减少用户的等待时间,提升用户体验。

    预解析的实现过程:

      1. 用meta信息来告知浏览器, 当前页面要做DNS预解析:<meta http-equiv="x-dns-prefetch-control" content="on" />
      1. 在页面header中使用link标签来强制对DNS预解析: <link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />

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

    PS:DNS预解析主要是用于网站前端页面优化,在SEO中的作用湛蓝还未作验证,但作为增强用户体验的一部分rel="dns-prefetch"或许值得大家慢慢发现。

    浏览器对网站第一次的域名DNS解析查找流程依次为:

    浏览器缓存-系统缓存-路由器缓存-ISP DNS缓存-递归搜索

    image.png

    Chrome内置了DNS Prefetching技术, Firefox 3.5 也引入了这一特性,由于Chrome和Firefox 3.5本身对DNS预解析做了相应优化设置,所以设置DNS预解析的不良影响之一就是可能会降低Google Chrome浏览器及火狐Firefox 3.5浏览器的用户体验。

    本文摘至网络

    相关文章

      网友评论

          本文标题:页面性能优化常用办法汇总

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