因事件堵塞导致页面卡顿

概述

上周星期四(2021/12/09)开始陆续有供应商反馈卖家中心页面公共模块(菜单栏)存在卡顿问题,特别是在进入商家报价页面,但是开发与测试在转测、转演、灰度阶段均未发现该性能问题。

分析

首先,我们需要了解页面的实现架构,卖家中心商家报价页面的公共模块ftl与右侧内容区ftl是通过Sitemesh框架整合而成的,公共模块ftl只定义了

的空架子,其元素内容通过引入执行seller-react-frame.js将元素内容注入到相关元素标签中。

另外,注入的元素内容并不是在seller-react-frame.js中实现的,而是在这个脚本中引入了其他脚本,引入的这些脚本是React实现topbar、slider组件后经webpack构建生成的。

右侧内容区是切切实实使用freemarker模板引擎实现的,数据由后端注入到页面中,相当于服务端渲染。

了解请求页面情况后,我们通过networkperformance性能分析看看

network分析

因事件堵塞导致页面卡顿_第1张图片

因事件堵塞导致页面卡顿_第2张图片

network面板可以看出,公共模块中的一个脚本原始大小有1.3Mgzip压缩后传输大小为375KB,从disk cache(磁盘缓存)读取耗时2.78s,清除缓存从CDN请求耗时2.88s,而公共模块其他的脚本原始大小都很小,只有一点几KB,请求耗时只有一两百毫秒。

显而易见,这个脚本过大了,需要做代码拆分。另外,从disk cache中读取也需要耗时,改用走memory cache(内存缓存),因为memory cache更快。

performance分析

在通过Performance检测页面性能发现公共模块(菜单栏)渲染的事件循环前面有一个执行耗时很长的事件 循环,这个事件循环是在初始化四级地址和品牌选项,四级地址树我们使用的ZTree.js处理的,里面init方法初始化树节点的事件复杂度比较高,因此我们看到检测到的执行时间较长(接近3秒) ,这更加堵塞了后面菜单栏事件循环的执行。

因事件堵塞导致页面卡顿_第3张图片

鉴于业务需求,四级地址树节点可以不用在刚进入页面时初始化,因此我将其脚本请求和执行放在了onload函数中,但是通过上图发现四级地址初始化还是先于渲染菜单栏执行,这是为什么呢?

image-20211213183218733.png

因事件堵塞导致页面卡顿_第4张图片

网络请求面板看一下脚本获取的先后顺序,发现公共模块脚本先于四级地址脚本获取,这使我更加困惑了。这时想到左侧菜单栏是React实现的,菜单栏数据是通过接口获取的,而不是像freemarker模板引擎是通过后端注入数据的,然后排查获取菜单接口发现,为了获取到菜单栏信息,竟然存在三个接口的串行调用,因为接口的串行调用导致渲染菜单栏的任务晚于四级地址初始化的任务加入到任务队列中,再加上四级地址初始化耗时较长,从而引起用户感知左侧菜单栏卡顿。

解决方案

(1)对公共模块中1.3M的脚本做代码拆分;

(2)优化脚本中的接口串行调用;

(3)从disk cache读取改成从memory cache读取;

(4)因为网络请求耗时不稳定,无法确保渲染菜单栏事件循环先于四级地址树节点初始化事件循环,因此可以在请求菜单栏接口成功后通过postMessage或者自定义事件通知可以开始初始化四级地址树节点;

你可能感兴趣的:(因事件堵塞导致页面卡顿)