优化对象本次优化针对web端的视频播放页面。白屏时间根据播放视频状态分为两种情况,即:外部进入,包括屏蔽页面进入、分享链接进入、用户详情页面进入和页面强制刷新。这时候白屏时间可以理解为浏览器输入url播放主要流程分为四个部分:全白屏,FP(FirstPaint)出现前的初始渲染视图和加载过程,session接口请求极度依赖session后的逻辑执行过程,loading消失,播放内部切换开始。手动点击【UserSession】列表项切换视频。这时候白屏时间可以理解为loading出现到消失的阶段。分为三个部分:session出现后加载的过程,加载过程消失开始播放。接下来新版本的视频目标达到2秒,老版本的视频可能会稍微慢一些,因为需要手动解析事件。完成的工作提前事件流分页(加载第一页数据后开始播放),无需等待数据准备好,第一时间渲染播放器、会话列表、事件流帧,播放前显示loading,以及给用户更直观的体验良好的体验,《感受快》推出新版WebWorker。因为返回的数据是字符串,所以需要手动解析成JSON。因此将下载和解析逻辑移至WebWorker中,充分利用CPU资源,避免影响主线程逻辑和渲染。Play前者主要是不影响事件流的数据流、解析和渲染。旧版本的视频下载和解析逻辑移到了WebWorker中。从整个页面中删除自定义滚动条。在开发人员工具的源代码面板中进行延迟加载。整体分析。使用ChromePerformance录制白屏到视频开始之间的片段进行分析:因为FP是用来记录页面第一次绘制像素的时间,之后会进入动态代码阶段,所以以下两部分分别以FP为界进行分析。FP前分析下面是FP前的细节截图从图中可以看出耗时任务主要分为两部分:my-details.js文件下载(目前经过gzip压缩后,体积为737.25KB)大任务问题定位文件下载阶段,打包文件过大,通过webpack打包插件webpack-bundle-analyzer分析,如图:经过分析,最大的三个文件是ts.worker.js(gzip1010.22KB)、my-details.js(gzip737.25KiB)和chunk-vendor.js(gzip442.56KiB),三个大文件中较大的模块如下:monaco-editor是最大的问题观点。在js文件执行阶段,详细分析bigTask。Performance放大截图如下,分析Task的执行顺序。执行流程图如下(只列出了主要流程,打包后执行流程会有所不同,但不影响分析):结合Performance结果可以看到,其中monaco-editor是仍然是最大的问题。进一步分析问题如下:chunk-vendor.js是项目的所有依赖库。可以看出它是用node_modules打包的,所以对性能影响很大。monaco-editor编辑器占很大篇幅。对于其他一些工具库,没有使用优化FP指标的关键是缩短资源的下载时间,减少阻塞浏览器渲染DOM的任务的执行时间。大致来说,方法有骨架图,分块加载,缓存,减少同步js代码,资源压缩,资源按需加载等,我们大部分的工作已经做好了,现在重点是有几个非常大的文件。因此总结出优化方案:拆分过大的js文件,尤其是monaco-editor的提取,因为用到的地方太多,很难做到按需加载,可以使用splitChunks分离代码实现它的相关模块是共享的。单独封装monaco-editor,最后减少请求资源大小和请求次数替换过大的第三方库,主要是lodash.js和moment.js工具库按需导入,特别是element-ui缓存部分static资源,提高加载速度ps:Webpack调优已完成,补充文档webpack性能调优报告FP分析问题定位FP后,进入代码执行阶段。下面是按照几个重要节点统计了8个session的耗时柱状图:从直方图可以看出,vue数据处理和dom挂载(挂载前)占用的面积很小,几乎没有影响白屏。重点关注mounted->playInitready这两个阶段,即playInitready->在初始数据(playInit)准备好之前播放,即获取playInit到正常播放的平均时间接近2秒。在极端情况下可能长达4-5秒。(统计日期为2021年12月28日,此时有些工作还未完成)拿到playInit后,只有两步,newPlayer(),执行play()方法,所以整个流程图如下:然后看看FP后ChromePerformance的详细截图。图中我们可以看到大任务分别是session接口请求后的逻辑任务、play/init接口请求后的逻辑任务、session_events接口请求后的逻辑任务。play方法networkrequest执行耗时最长的是事件流接口(session_events)播放初始数据接口(play/init),结合代码流程图和性能截图,最后总结一下目前存在的问题:session_events接口(事件流)目前是异步执行的,在视频播放的情况下可能会有延迟,不符合产品要求。session_events接口本身存在数据耦合太大导致下载时间慢的问题(需要和后端通信)。会话接口(会话列表)不是必要的前提条件。现在之所以前面是因为其他接口依赖sessionId,但是sessionId和sessions接口之间没有强关联。在外部访问的情况下,可以直接从url参数中获取sessionId。在内部切换的情况下,可以直接在当前环境中获取sessionId会话接口(会话详情)。只提供老版本的视频资源url,重复play/init函数。sources接口和play/init接口只依赖sessionId,所以获取接口数据后不需要post任务。任务太大耗时,因为播放All之前的所有任务都要执行,所以异步解决不了问题。优化方案杀掉session接口(sessiondetails),将资源url统一放在paly/init接口,减少网络请求(需要后端配合)并并行执行session、sources、session_events和paly/这四个init接口减少彼此不必要的等待。session_events接口变成了两个。第一个只获取标题信息以减少资源下载时间,另一个获取全量数据(需要支持分页)。播放前,只通过第一个接口,加载TitleInformation第二个接口异步请求所有数据存入内存,在用户展开时读取,如果用户点击展开时还没有返回全量数据,然后根据点击的item的索引然后扩展对应于寻呼请求的数据。这时候全量数据到达后,就需要采用去重策略。使用WebWorker将获取数据后的耗时任务丢给子线程,并行+时间片执行调度任务,分配不同的任务。优先级,然后切片一个长任务,保证重要的任务优先执行,其他任务或者没有依赖关系的任务次要执行(打主任务以外的其他任务)。事件流使用虚拟列表技术,减少渲染消耗(不仅解决了第一次渲染问题,也解决了后续的滚动性能问题)增加缓存,采用ServiceWorker技术,缓存接口请求,Google的Workbox类库,当前版本只缓存sources、paly/init和session_events的三个接口和部分静态资源,后续逐步扩展到全站缓存ps:现阶段已经加入了缓存,前端缓存机制为为提升网站性能而产生——ServiceWorker最终流程图
