前端性能优化之统计篇(一)

引言

身为前端我们应该算是与用户体验直接相关的一个岗位,也是与到达率、转化率等等指标息息相关,我们是否有遇到过这些场景:上线了某些活动第二天往往就有产品找过来,这个活动到达率怎么感觉这么低?是不是页面加载耗时比较高?这个页面怎么白屏这么久?怎么感觉咱们的页面没有比人家的加载快呢?听到这些你是不是有些怒火中烧?你还能忍得了老?是不是有点想拿刀的冲动?

冷静些,面对重重质疑我们是要拿起数据的武器维护自己的合法权益。我们总不能空口白牙的与产品在这掰扯吧,我们是不是能够建立一套标准?建立一套体系?体系化的数据来怼回去。心中默默按下决心决定退出整套的性能方案:建立数据统计标准和数据大盘、性能优化方案&落地、性能优化防劣化等等。

为什么性能优化?

性能优化毋庸置疑是一个非常重要的方向,那么性能优化到底有哪些价值呢?我们主要从用户体验、商业价值、技术方案三个方面来进行说明。

用户体验

  • 性能也就是指加载速度,高性能的系统可以改善用户体验。

  • 系统加载速度对用户的参与度有着明显的影响,国外网站Kissmetrics的数据统计表明,47%的访问者希望网站加载时间在2秒以内,如果加载时间超过3秒,40%的访问者将会离开网站。

  • 没有人愿意忍受一个速度慢的网站, 当页面加载时间从1秒变为10秒时,移动站点访问者跳出率增加了123%.

  • 也有一项消费者研究表明,人们对移动设备加载速度延迟有着明显的压力反应.

商业价值

  • 用户的体验好坏关系到,用户参与度、用户的留存,系统的转化率,和系统的体验与传播,这最终影响的是收入。

  • 沃尔玛研究发现,网页加载用时每减少100ms收入就会增加1%。

  • 零售商AutoAnything 将页面加载时间减少一半时,他们的销售额增长了 12% 到 13%。

怎么衡量页面性能?

google-RAIL

google 开发者提出了一种 RAIL 模型来衡量应用性能,即:Response、Animation、Idle、Load,分别代表者 web 应用生命周期的四个不同方面。并指出最好的性能指标是:

1.响应:输入延迟时间(从点按到绘制)小于 100 毫秒。 用户点按按钮(例如打开导航)。

2.动画:每个帧的工作(从 JS 到绘制)完成时间小于 16 毫秒。 用户滚动页面,拖动手指(例如,打开菜单)或看到动画。 拖动时,应用的响应与手指位置有关(例如,拉动刷新、滑动轮播)。 此指标仅适用于拖动的持续阶段,不适用于开始阶段。

3.空闲:主线程 JS 工作分成不大于 50 毫秒的块。 用户没有与页面交互,但主线程应足够用于处理下一个用户输入。

4.加载:页面可以在 1000 毫秒内就绪。 用户加载页面并看到关键路径内容。

我们从中收到启发,从上面的指标体系中抽象出与业务转化关系比较紧密的标准:可交互时长。

可交互时长(技术栈以vue为例)

可交互时长 TTI(Time to Interactive) 指的是应用既在视觉上都已渲染出了,可以响应用户的输入了。上文提到可以按如下方式计算TTI

makefile 复制代码
TTI: domContentLoadedEventEnd - navigationStart,

事实上这是静态资源加载完毕的时长,未包括调用API接口,以及拿到数据后页面渲染的时间。我们基于上面的指标为基础结合我们业务本身,对上面的指标进行扩展升级建立了一套独立用户可交互时长的统计方式与计算标准。

将页面整个请求过程分为如下几个阶段,并且对没有阶段耗时就行统计,这个对这个过程进行分段就知道应该针对哪些阶段进行优化。

  1. 模版加载阶段:app内webview初始化到执行到html页面script时耗时。

    vbscript 复制代码
    //模版加载耗计算方式
    // new Date().getTime()为执行到html模版中script模块的时间
    
    const templateTime = new Date().getTime()
    template_loaded = templateTime - performance.timing.navigationStart
  2. 静态资源阶段:html模版中script模块的时间到app.js头部入口的时间

    vbscript 复制代码
    //静态资源加载技术方式
    const sourceTime = new Date().getTime()
    source_loaded = sourceTime - templateTime
  3. 登录阶段:登录阶段根据页面情况可以区分是强制登录、游客模式两种,登录花费的时间在数据统计大盘中应该剔除掉,它不属于性能加载花费的时间

    arduino 复制代码
    //登录耗时
    const login_loaded = login_end - login_start
  4. store、其他业务组件初始化、强制业务授权判断时间

    vbscript 复制代码
    //初始化阶段耗时
    cosnt initTime = new Date().getTime()
    const init_loaded = initTime - login_loaded - sourceTime
  5. core核心逻辑耗指所有页面都需要用到的接口或者所有页面都依赖的接口,项目级别接口的请耗时

vbscript 复制代码
    // 核心接口耗时
    const coreApiTime =  new Date().getTime()
    const core_loaded = coreApiTime - initTime
  1. 路由决策阶段:核心接口请求后,根据请求情况决策应该路由那个页面(页面入口不一定唯一)
vbscript 复制代码
    // 路由决策耗时
    const routerTiem = new Date().getTime()
    const router_loaded = routerTiem - coreApiTime
  1. 页面请求接口耗时指每个页面可以有自己单独的接口,强制在vue的created钩子中请求
javascript 复制代码
    //page.vue
    export default {
        create() {
            const createTime = new Date().getTime()
    
            await pageApi()
    
        }
    }
  1. 页面渲染耗时指vue中create函数到mounted函数的耗时
javascript 复制代码
    //page.vue
    export default {
        create() {
            const createTime = new Date().getTime()
            await pageApi()
        },
        mounted() {
            const mountedTime = new Date().getTime()
        }
    }

这样我们把整个页面加载过程分为了几个阶段,每个阶段基于项目的埋点工具进行属性上报,就可以建立完整的数据大盘,这种统计方式有点类似于分治思想。每个接段耗时可能影响的内容和每个阶段耗时的高度就可以很清晰的看到。

小结

这样我们就可以得到一个可交互时长的大盘,方案上报的逻辑基本适合全部h5项目,方便我们后续的推广,并且上报的数据还可以进行自定义字段:区分页面、项目、机型、网络环境等等内容。

通过大盘确实发现5.4号的上线影响了项目的性能,那么我们就可以根据各个阶段的情况进行分析了,针对我们发现的问题怎么优化呢?

不要走开,请大家期待后续的优化分析和优化策略。

相关推荐
昨天;明天。今天。1 分钟前
案例-任务清单
前端·javascript·css
zqx_71 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己1 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称2 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色2 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2342 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河2 小时前
CSS总结
前端·css
BigYe程普3 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
余生H3 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍3 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发