前端性能优化(1)

参考掘金小册https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5bdc7198518825171726cfce

网络相关

DNS 预解析

  • DNS 解析也是需要时间的,可以通过预解析的方式来预先获得域名所对应的 IP。

  • 域名解析:从域名查询IP的过程,这个过程一般都很快的,但也会引起延迟。一般浏览器会适当的对解析结果缓存,并对页面中出现的新域名进行预解析,但并不是所有的浏览器都会这么做,为了帮助其它浏览器对某些域名进行预解析
  • DNS查询需要个RTT时间,在浏览器级别,系统级别都会有层DNS缓存,之前解析过的可以直接从本机缓存获取,以减少延迟。

缓存

使用 HTTP / 2.0

  • 因为浏览器会有并发请求限制,在 HTTP / 1.1 时代,每个请求都需要建立和断开,消耗了好几个 RTT 时间,并且由于 TCP 慢启动的原因,加载体积大的文件会需要更多的时间。

  • 在 HTTP / 2.0 中引入了多路复用,能够让多个请求使用同一个 TCP 链接,极大的加快了网页的加载速度。并且还支持 Header 压缩,进一步的减少了请求的数据大小。

  • HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能。

  • 在 HTTP/1 中,为了性能考虑,我们会引入雪碧图、将小图内联、使用多个域名等等的方式。这一切都是因为浏览器限制了同一个域名下的请求数量(Chrome 下一般是限制六个连接),当页面中需要请求很多资源的时候,队头阻塞(Head of line blocking)会导致在达到最大请求数量时,剩余的资源需要等待其他资源请求完成后才能发起请求。

  • 在 HTTP/2 中引入了多路复用的技术,这个技术可以只通过一个 TCP 连接就可以传输所有的请求数据。多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也间接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。

预加载


  • 图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度。这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速、无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验。
  • 图片等静态资源在使用前提前请求。
    资源后续使用可以直接从缓存中加载,提升用户体验。

预渲染

  • 可以通过预渲染将下载的文件预先在后台渲染,可以使用以下代码开启预渲染

  • 预渲染虽然可以提高页面的加载速度,但是要确保该页面百分百会被用户在之后打开,否则就白白浪费资源去渲染

优化渲染过程

懒执行

  • 懒执行就是将某些逻辑延迟到使用时再计算。该技术可以用于首屏优化,对于某些耗时逻辑并不需要在首屏就使用的,就可以使用懒执行。懒执行需要唤醒,一般可以通过定时器或者事件的调用来唤醒

懒加载

  • 懒加载就是将不关键的资源延后加载。懒加载的原理就是只加载自定义区域(通常是可视区域,但也可以是即将进入可视区域)内需要加载的东西

文件优化

图片优化

  • 不用图片,用css
  • 对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用 CDN 加载,可以计算出适配屏幕的宽度,然后去请求相应裁剪好的图片。
  • 小图使用 base64 格式
  • 将多个图标文件整合到一张图片中(雪碧图)

防抖,节流

防抖

  • 通过监听 scroll 事件,检测滚动位置,根据滚动位置显示返回顶部按钮
  • 通过监听 resize 事件,对某些自适应页面调整DOM的渲染(通过CSS实现的自适应不再此范围内)
  • 通过监听 keyup 事件,监听文字输入并调用接口进行模糊匹配

实现

  • 多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行
  • 原理:对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时。
function debounce(method,delay){
    let timer = null;
    return function(...args){
        //es5 args = arguments;
        // 这里返回的函数是每次用户实际调用的防抖函数
      // 如果已经设定过定时器了就清空上一次的定时器
      // 开始一个新的定时器,延迟执行用户传入的方法
        if(timer) clearTimeout(timer);
        timer=setTimeout(()=>{
            method.apply(this,args)
        },delay);
    }
}

节流

  • 当我们做图片懒加载(lazyload)时,需要通过滚动位置,实时显示图片时,如果使用防抖函数,懒加载(lazyload)函数将会不断被延时,只有停下来的时候才会被执行,对于这种需要实时触发事件的情况,就显得不是很友好了。所以使用节流

实现

  • 规定函数在某时间段内最多执行一次

  • 函数在n秒内最多执行一次

  • 下一次函数调用将清除上一次的定时器

    • 若函数执行的时间间隔小于等于规定时间间隔则用setTimeout在规定时间后再执行
    • 若函数执行的时间间隔大于规定时间间隔则执行函数,并重新计时
function throttle(func,interval){
    let timer=null;
    let startTime = new Date();
    
    return function(...args){
       
        if(timer) clearTimeout(timer);
        
        let curtime = new Date();
        if(curtime-startTime{
                func.apply(this,args);
            },curtime-startTime)
        }else{
            //大于时间间隔,重新计时并执行函数
            startTime = curtime;
            func.apply(this,args);
        }
    }
}

提高页面加载速度

减少HTTP请求

  • 百分之八十九十时间花在了下载页面中所有组件进行的HTTP请求上,因此改善响应时间最简单途径就是减少HTTP请求的数量
1. 使用雪碧图 CSS Sprites
  • 将多张图片融合在一张图降低图片数量
  • 合并后的图片会比分离图片的总和要小,因为它降低了图片自身的开销,譬如颜色表,格式信息等
2. 字体图标
  • 减少图片使用,减少http请求,字体图标还能设颜色,大小
3. 合并脚本,样式表
  • 看个人

使用CDN

  • CDN内容分发网络是一组分布在多个不同地理位置的Web服务器,用于更加有效地向用户发布内容,在优化性能时,会根据距离的远近来选择。

  • CDN将网站的资源发布到离用户最近的网络边缘,用户可以就近取得资源内容。

  • cDN通常部署静态内容:JavaScript脚本、CSS样式表、图片、图标、Flash等,不包括html页面。

  • CDN系统能够实时的根据网络流量和各节点的连接,负载状况以及用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的就是使用户能够就近的获取请求数据,解决网络访问拥挤状况,提高用户访问系统的响应时间。

  • 用户发起内容请求时,通过cdn厂商的智能DNS域名解析拿到cdn厂商边缘节点服务器的ip(cdn厂商会在运营商注册),然后向边缘节点服务器发起请求,请求内容数据(这件事情由浏览器完成),边缘节点会检测当前节点是否有数据,如果没有就去front(父级节点,父级可能还会有父级节点,不同的网络环境策略会略有不同)节点要,如果还找不到就去源站拿,并依次序返回。如果某个边缘节点可以找到,会先校验内容有效期,当确定有效期之后返回给用户

  • 前端需要被加速的文件大致包括 js、css、图片、视频、和页面等文件,页面文件比较特殊(有动态和静态之分)我们稍后再聊,先聊聊js、css、图片和视频文件。这些文件和页面(html\jsp\aspx等)最大的区别是:这些文件都是静态的,改动较小,了解上面cdn工作原理之后我们就可以发现这类静态文件最适合做cdn加速。我们把这些静态文件通过cdn分发到全国乃至世界的各个节点,用户就可以在距离最近的边缘节点拿到所需要的内容,从而提升内容下载速度加快网页打开速度达到性能优化的目的

  • jsp动态页面是不适合做cdn加速的。原因:参照上面讲的cdn工作原理,由于页面是动态的,内容的有效期就比较活跃。假如我们对动态页面做了cdn加速,那么场景应该是这样的:用户——>边缘节点(验证有效期发现失效)——>源站。经过这个过程才能拿到页面,这样并没有起到加速的作用反而更慢了,那我们还不如直接去源站拿(当然我们可以要求cdn厂商做定制化开发)。

  • 静态页面(html)也是比较适合做cdn加速的。但是静态页面也分纯静态页面和非纯静态页面。

  • 如果非纯静态页面做cdn加速,参照上述的cdn工作原理,会出现用户没有通过任何服务器鉴权认证也可以正常在cdn边缘节点拿到想要访问页面(要求cdn厂商做定制化开发也可以避免这种情况)。不过我们可以采用前后端彻底分离的方式(js发ajax请求的方式验证用户是否可以通过鉴权)来解决动态页面和非纯静态页面不适合做cdn加速的问题。

提高浏览器并发连接数(有http2不适合了)
  • 不同的浏览器对单个域名的最大并发连接数有一定的限制,HTTP/1.0和HTTP/1.1也不相同。比如HTTP/1.1协议下,IE6的并发连接数限制是2个;而在HTTP/1.0下,IE6的并发连接数可以达到4个。在其它浏览器也有类似的限制,一般是4~8个。这个时候,如果浏览器同时对某一域名发起多个请求,超过了限制就会出现等待,也就是阻挡。
  • 那么为了解决阻挡这一问题,我们可以对某些URL的域名分散处理,比如我们的图片域名,一般用类似img.guoweiwei.com的域名,当一个页面包含20多张图片的时候,那至少有10几个请求会被阻挡,而如果我们分散到img0.guoweiwei.com/img1.guoweiwei.com/img2.guoweiwei.com/…等不同域名的时候,至少这20个图片请求会并发进行,网站打开速度会明显提升很多。类似的,可以对一些css/js的域名同样处理。
  • 但是域名分散会耗费连接时间
给静态资源单独域名
  • 如果细心一点,你会在淘宝的网站发现这两个现象,淘宝有很多类似img0.tbcdn.cn这样的域名。
    再另外提一点优化,那就是为什么用img0.tbcdn.cn这个域名,而不是img0.taobao.com呢?这个得从cookie说起,淘宝的cookie已经非常大了,据说曾接近1K,如果用后面的域名,那每次请求图片都会带上长长的cookie,后果可想而知,不仅使得网络请求变慢,而且还浪费了带宽,而淘宝图片服务器并不需要这些cookie。这就是所说的cookie污染,为了解决这一问题,单独的域名是很有必要的。

你可能感兴趣的:(前端性能优化(1))