08月11, 2017

优化页面性能的基本思路

简单介绍下进行页面性能优化的基本思路和准备工作。

基本思路

  1. 确定关键指标
  2. 获取关键指标
  3. 统计数据
  4. 分析数据:可以通过chrome插件直观显示;或者分析打点(埋点)日志
  5. 确定优化方式
  6. 数据对比效果
  7. 确定一套代码规范,将性能检测加入发布上线流程

下面着重介绍下通过日志进行数据分析的方法,简单来说就是向服务器主动触发带有关键指标数据的请求。

通过日志分析数据

  • 在页面的底部加载一段获取关键指标的JS。可以通过window.performance.timing 来进行统计。对于不支持window.performance.timing的浏览器,可以通过在页面不同的地方进行时间记录,手动计算加载时间。
  • 引用一张与时间相关的经典图:

    timing

function getPerformanceTiming() {  
  var performance = testPerformance();

  if(performance === false) return;

  var t = performance.timing;
  var times = {};

  //【重要】重定向的时间
  times.redirect = t.redirectEnd - t.redirectStart;

  //【重要】DNS 查询时间
  times.dns = t.domainLookupEnd - t.domainLookupStart;

  // TCP 建立连接完成握手的时间
  times.connect = t.connectEnd - t.connectStart;

  //【重要】内容加载完成的时间
  times.request = t.responseEnd - t.requestStart;

  //【重要】读取页面第一个字节的时间
  times.ttfb = t.responseStart - t.navigationStart;

  //【重要】白屏时间,用户开始看到内容
  times.white = t.domLoading - t.navigationStart;

  //【重要】内容渲染的时间
  times.render = t.domComplete - t.domLoading;

  // DOM树创建好了,内容还未加载,如图片啥的
  times.active = t.domInteractive - t.navigationStart;

  //【重要】DOM加载完成, jquery中的dom ready
  times.domready = t.domContentLoadedEventEnd - t.navigationStart;

  // 页面加载时间
  times.loadPage = t.loadEventEnd - t.navigationStart;

  return times;
}

// 因为有些时间需要在load事件完成后才能获得,比如loadEventEnd
// 【重要】并且把getPerformanceTiming方法放在异步中触发
window.onload = funcion(){
    setTimeout(function(){
        var performance = testPerformance();

        if(performance !== false){
            times = getPerformanceTiming();
        }
    }, 0)
}
// 统计CSS, JS,Tag个数,这里的document可以换成是其他指定元素
function getElePermance(){
    var tagCount = document.querySelectorAll('*').length,
        imgCount = document.querySelectorAll('img[src]').length,
        bgImgCount = document.querySelectorAll('[style*="background-image"]').length;

    var counts = {
      tagCount: tagCount,
      imgCount: imgCount + bgImgCount
    };

    return counts;
}
  • 然后再向某服务器上发一个请求。这里呢,可以加载一张服务器上的图片,size越小越好,并且把关键指标,以及有用的信息作为query string带在图片地址的后面。

    var report = (function(){
      // 这里使用闭包,保证请求能够在img被销毁前发出
      var imgs = [];
      return function(src){
        var img = new Image();
        imgs.push(img);
        img.src = src;
      }
    })();
    
    report('/static/srp.gif?'+queryStr);
    
  • 服务器上接收到请求后一般都会有访问日志,这里以nginx为例。在nginx的access.log中可以看到访问图片的请求,有用的信息还包括有IP,请求时间,UA等。

    127.0.0.1 - - [10/Aug/2017:09:47:13 +0800] "GET /static/srp.gif?redirect=0&dns=0&connect=1&request=11&ttfb=37&white=66&render=598&active=587&domready=589&loadPage=664&tagCount=45&imgCount=0& HTTP/1.1" 200 43 "http://localhost:1111/query/pc" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.31 Safari/537.36"
    
  • 因为nginx日志中同时还会存在其他的访问记录,所以我们需要进行一次预处理,只提取出访问图片的记录。需要注意的是,access.log文件的权限有可能是root或者是nginx,我们当前用户不一定有读写权限。

    LOG_TIME=`date -d yesterday "+%Y%m%d"`
    cp "/var/log/nginx/access.log-${LOG_TIME}.gz" /home/yourfloder/
    # 如果需要修改权限
    chown youruser:yourgroup "/home/yourfloder/access.log-${LOG_TIME}.gz"
    
  • 拿到仅有访问图片的二次处理后的文件后,就有了关于页面性能的原始数据。接下来就可以做不同维度的分析。比如最简单的,分析出相同页面的平均性能。

  • 如果日志的数量是海量的,比如是线上的统计日志,还可以利用hadoop 分布式来处理日志。

参考

  1. 初探 performance – 监控网页与程序性能
  2. 阮老师的Performance API
  3. window.performance 详解

本文链接:https://imjiaolong.cn/post/perfornamce.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。