干货 | 秒开率70%+,携程金融SSR应用性能监测与优化

本文介绍了携程金融如何通过性能监测和优化,将SSR应用的秒开率提升至70%以上。重点讨论了页面首屏时间、CLS的性能指标,采用真实用户监控,并分享了DNSDuration、TCPDuration、RequestDuration等关键阶段的优化策略,以及数据处理和分析的方法。

作者简介

 

建成,携程高级前端开发,对前端工程化、性能优化、效率提升等方面有浓厚兴趣。

背景

对于一款互联网产品来说,用户体验始终扮演着重要的角色,尤其是在后互联网时代,增量见顶,竞争方向逐渐转为存量用户,体验的好坏可能直接决定着一个用户的去留。

据统计,网页加载时间从 1 秒增加到 3 秒,跳出率就会提高 32%;如果网页加载时间从 1 秒增加到 6 秒,跳出率就会上升 106%。

基于此,携程金融前端团队对内部SSR应用的性能实施了一系列的治理,本文将从性能监测、数据处理与分析、优化之路等方面来分享。

一、性能

用户体验是一个比较感性的概念,每个人的感受可能都不太一样,较难进行衡量。基于此,我们首先要把用户体验进行量化,使其可衡量和监测。

根据业内经验和相关分析,用户体验和页面首屏时间、页面累积布局偏移量有较强相关性,通过计算和监测这两个指标可以来衡量应用的用户体验。


二、性能监测

从技术方面来讲,前端性能监控主要有两种方式,一种是合成监控(Synthetic Monitoring,SYN),另一种是真实用户监控(Real User Monitoring,RUM)。

为了凸显用户真实的体验,我们采用了真实用户监控(即通过用户实际操作产生的一系列性能指标数据进行监测)。


2.1 页面首屏时间

页面首屏时间主要涉及到浏览器请求和渲染流程。

2.1.1 性能指标选定

为了能监测应用全链路性能表现,我们在整个链路中选取了最重要的几个节点,分别如下:

1a5bbc829b5810ecffc135d9aabdaf11.png

  • DNSDuration:衡量DNS时长

  • TCPDuration:衡量TCP链接时长

  • TTFBDuration:衡量浏览器接受到第一个字节的时长

  • RequestDuration:衡量SSR服务端处理时长

  • FCP:衡量携程端首屏时间

  • DOMContentLoaded:衡量去哪儿和携程金融app首屏时间(native loading隐藏时间点)

  • Load:衡量所有资源加载并执行时长

2.1.2 最佳表现(P90)

  • RequestDuration:300ms

  • FCP:800ms

  • DOMContentLoaded:1000ms

2.1.3 性能指标的收集

指标的收集会用到两个api,分别为监测Android的PerformanceObserver和监测iOS的 Performance.timing

// 创建性能监测实例
function createPerformanceObserver(callback) {
    // Create the performance observer
    const po = new window.PerformanceObserver(list => {
        callback && callback(list)
    })


    return po
}


// 性能监测处理函数
function performationAduitCallback(list) {
    for (const entry of list.getEntries()) {
        if (entry.entryType === 'navigation') {
              // navigation
              const DNSDuration = entry.domainLookupEnd - entry.domainLookupStart
              const TCPDuration = entry.connectEnd - entry.connectStart
              const RequestDuration = entry.responseEnd - entry.requestStart
              const TTFBDuration = entry.responseStart - entry.startTime
              const DOMCompleteDuration = entry.domContentLoadedEventEnd - entry.startTime
              const DOMLoadDuration = entry.duration


              // FCP
              let FCPDuration = 0;
              if (performance && performance.timing) {
                  FCPDuration = window.headReadyTime ? window.headReadyTime - performance.timing.navigationStart : 0;
              }


              const performanceParams = Object.assign({}, extraInfo, {
                  DNSDuration,
                  TCPDuration,
                  RequestDuration,
                  TTFBDuration,
                  FCPDuration,
                  DOMCompleteDuration,
                  DOMLoadDuration,
              })


              sendPerformance(performanceParams)
        }
    }
}


// 性能指标监测(安卓)
function performationAduitAndroid() {
    try {
        const PO = createPerformanceObserver(performationAduitCallback)


        PO.observe({
            entryTypes: ['navigation'],
        })
    } catch (e) {
        console.log('performationAduitAndroid error', e)
    }
}
// 性能指标监测(IOS)
function performationAduitIos() {
  const timing = performance && performance.timing
  if (!timing) {
      return
  }


  const start = timing.navigationStart
  const param = util.merge(
      {},
      {
          DNSDuration: timing.domainLookupEnd - timing.domainLookupStart,
          TCPDuration: timing.connectEnd - timing.connectStart,
          RequestDuration: timing.responseEnd - timing.requestStart,
          TTFBDuration: timing.responseStart - start,
          FCPDuration: window.headReadyTime ? window.headReadyTime - start : 0,
          DOMCompleteDuration: timing.domContentLoadedEventEnd - start,
          DOMLoadDuration: timing.loadEventEnd - start,
      }
  )


  const performanceParams = Object.assign({}, extraInfo, param)
  sendPerformance(performanceParams)
}

2.2 页面累积布局偏移量(CLS)

CLS (Cumulative Layout Shift) 是Web Vitals指标之一,主要用于测量整个页面生命周期中,布局移位的分值,以此衡量视觉稳定性。

2.2.1 性能指标的选定

衡量页面累积布局偏移量的指标只有一个,就是CLS。通过减少CLS,可以减少用户因为页面突然移位造成的误触概率。

2.2.2 最佳表现(P90)

  • CLS:0.05

2.2.3 性能指标的收集

CLS的收集同样使用 PerformanceObserver 这个api,这个api会有兼容性问题,只能应用于Android。

// 创建性能监测实例
function createPerformanceObserver(callback) {
    // Create the performance observer
    const po = new window.PerformanceObserver(list => {
        callback && callback(list)
    })


    return po
}


// CLS处理函数
function clsAduitCallback(list) {
    for (const entry of list.getEntries()) {
        if (entry.entryType === 'layout-shift') {
            // CLS
            const CLS = entry.value ? entry.value * 1000 : 0
            const CLSParams = Object.assign({}, extraInfo, { CLS })
            sendPerformance(CLSParams)
        }
    }
}


// CLS数据指标(安卓)
function clsAduit() {
    try {
        const clsPO = createPerformanceObserver(clsAduitCallback)


        if (window.PerformanceObserver.supportedEntryTypes.includes('layout-shift')) {
            clsPO.observe({
                type: 'layout-shift',
                buffered: true,
            })
        }


        window.addEventListener('load', () => {
            // 延迟1s取消监听
            setTimeout(() => {
                clsPO.disconnect()
            }, 1000)
        })
    } catch (e) {
        console.log('cls error===>', e)
    }
}

三、数据处理与分析

数据收集好之后,还需要对数据进行加工处理,才能客观的反应出应用的性能状况。加工处理的方式如下:

3.1 百分位数

在数据分析中,我们通常想衡量大部分用户的性能表现,而所有统计的数据中会存在一些异常的数据,因此需要对原始数据取百分位数进行分析。目前金融内部会取P50和P90两个百分位数进行分析。


3.2 分端统计

金融大部分应用主要运行在携程端、携程金融端和去哪儿端,为了衡量各端的性能情况,我们将数据进行了分段统计。


3.3 秒开率统计

页面首屏时间能反映出大部分用户的性能表现;秒开率能反应出性能最佳表现的用户所占比例。通过这两个数据基本上能衡量出我们应用的性能状况。

秒开率计算方法 = count(固定时间段内页面首屏时间 < 1s) / count(*)


四、优化之路

通过上面的数据处理和分析,已经能准确了解到应用的整体性能表现以及各阶段性能情况,下面就有针对性地对各阶段进行优化处理。

4.1 DNSDuration

  • 选择性的使用DNS Prefetch

隐式 DNS Prefetch:浏览器会对页面中和当前域名不在同一个域的域名进行prefetch。因此显式DNS Prefetch应用于页面中未出现的域名。所以二级页面中的域名如果在首页中没有出现,可以选择使用DNS Prefetch。


4.2 TCPDuration

前端的能力很难对TCP连接阶段进行优化,但是可以利用TCP的一些特点,进行资源获取的优化。

  • 首页的html size小于14k

由于TCP Slow Start的原因,我们应尽可能的将首页的html size控制在14k以内,使首页数据可以在一个TCP包中发送到浏览器,加快渲染速度。

  • Http1 → Http2减小TCP连接次数和减少渲染阻断

应用HTTP2多路复用和浏览器渲染流程。


4.3 RequestDuration

  • 优化服务端接口响应时长

  • 非必要接口放到客户端异步请求


4.4  FCP

  • CSS做内联


4.5 DCL

  • Preload提升阻塞JS下载优先级

  • 将webpack打包出的Bundle JS同步变异步(Async)

  • 减小JS Size:抽离公共chunk

  • 高效利用缓存:根据改动频率split chunk + ContentHash + 缓存


4.6 onload(页面完全展示)

  • 接口数据缓存:与用户关联度较小的接口

  • 图片转webp

  • 图片size控制

  • 字体preload


4.7 CLS

  • 尽可能可以不发生移位

  • 发生移位的位置尽可能影响更少的区域

  • 移位的距离尽可能小,且使用动画

  • 骨架图


五、总结

通过以上的治理步骤,金融主要SSR应用的秒开率都提升到了70%以上,且做到实时监控性能变化,一旦性能出现问题,可以及时感知并采取措施进行解决。

相信通过以上的努力,可以给金融所有的用户一个良好的用户体验,从而助力产品发展。

【推荐阅读】

97cafef5d09075399253f5daefc464e5.png

 “携程技术”公众号

  分享,交流,成长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值