关于vue.js:记一次播放器页面白屏时间优化方案

47次阅读

共计 3046 个字符,预计需要花费 8 分钟才能阅读完成。

优化对象

此次优化是针对,Web 端视频播放页面。白屏工夫依照播放视频状态有两种状况,别离是:

  • 内部进入,包含筛选页进入、分享链接进入、用户详情页进入和页面强制刷新,此时白屏工夫能够了解为浏览器输出 url 到播放器播放的工夫,次要流程分为四局部:

    • 齐全白屏,FP(First Paint)之前流程
    • 初始渲染视图和 loading 呈现,sessions 接口申请极其依赖逻辑执行
    • sessions 之后的流程
    • loading 隐没,开始播放
  • 外部切换,通过手动点击【用户会话】列表项切换视频,此时白屏工夫能够了解为 loading 呈现到隐没的阶段,有三局部:

    • loading 呈现
    • sessions 之后的流程
    • loading 隐没,开始播放

整顿流程图示如下:

预期后果

失常状况下,新版本视频指标达到 秒开,老版本视频因为须要手动解析事件,可能会稍慢一些。

已做工作

  1. 事件流分页(加载第一页数据后即开始播放)
  2. 提前渲染,不期待数据筹备结束,第一工夫渲染播放器、会话列表和事件流框架,播放前展现 loading,给用户视觉上更好的体验,「感觉快」
  3. 引入 Web Worker

    1. 新版本视频因为返回数据为字符串,须要手动解析为 JSON,因而下载和解析逻辑移入 Web Worker,充分利用 CPU 资源,防止影响主线程逻辑和渲染,播放前次要是不影响数据流,事件流的解析和渲染。
    2. 老版本视频下载和解析逻辑移入 Web Worker。
  4. 全页面去掉自定义滚动条
  5. 开发者工具 source 面板懒加载

整体剖析

借助 Chrome Performance 录制白屏至视频开播之间的片段,进行剖析:

因为 FP 用于记录页面第一次绘制像素的工夫,之后即会进入动静代码阶段,所以上面以 FP 为界线,别离剖析前和后两局部。

FP 之前剖析

上面是 FP 之前的详情截图

从图中能够看出耗时的工作次要为两局部:

  • my-details.js 文件下载(目前 gzip 压缩之后,体积为 737.25 KB)
  • 一个大 Task

问题定位

  1. 文件下载阶段,打包文件过大,通过 webpack 的打包插件 webpack-bundle-analyzer 剖析,如图所示:

通过剖析,三个最大的文件是 ts.worker.js(gzip 1010.22 KB)、my-details.js(gzip 737.25 KiB)和 chunk-vendor.js(gzip 442.56 KiB),三个大文件中的较大模块如下:


其中 monaco-editor 是最大的一个问题点。

  1. js 文件执行阶段,具体分析下大 Task,Performance 放大截图如下

剖析 Task 执行程序,执行流程图如下(只列出次要流程,打包之后执行流程会不同,但不影响剖析):

联合 Performance 后果,能够看出其中 monaco-editor 依然是最大的问题点。

进一步剖析问题如下:

  • chunk-vendor.js 是我的项目所有的依赖库,从它是打包了 node_modules 能够看出,所以很影响性能
  • monaco-editor 编辑器占了很大体积
  • 对于一些其余的工具库,未采纳按需引入的形式

优化计划

优化 FP 指标,要害是缩短资源的下载工夫,以及缩小阻塞浏览器渲染 DOM 的工作的执行工夫,通常来说的伎俩有骨架图、分块加载、缓存、缩小同步 js 代码、资源压缩和资源按需加载等等。对咱们来说大部分工作曾经做了,当初关键点为有几个文件很大。

因而,总结下优化计划:

  1. 拆分过大 js 文件,尤其是 monaco-editor 的抽离,因为用的中央太多了,导致很难做成按需加载了的了,能够应用 splitChunks 拆散代码并实现相干模块共享。独自打包monaco-editor,最终缩小申请资源的大小和申请次数
  2. 替换过大的第三方类库,次要是 lodash.js 和 moment.js
  3. 工具库采纳按需引入的形式,尤其是 element-ui
  4. 缓存局部动态资源,进步加载速度

ps: Webpack 调优已实现,补充文档 webpack 性能调优报告

FP 之后剖析

问题定位

FP 之后就进入了代码执行阶段,上面为 8 个会话依照几个重要节点进行耗时统计的柱状图:

由柱状图能够看出,vue 数据处理和 dom 挂载(mounted 之前)占用了很小的范畴,简直对白屏没有任何影响。重点关注两个阶段

  • mounted -> playInit ready,即播放初始数据(playInit)筹备好之前
  • playInit ready -> play,即拿到 playInit 到失常播放

这两个阶段加一起的耗时均匀靠近 2 秒,极其状况可能达到 4 – 5 秒。(统计日期 2021 年 12 月 28 日,此时有局部已做工作还没有实现)
拿到 playInit 之后就只有两个步骤,new Player(),执行 play() 办法,因而整个的流程图如下:

而后再看下 Chrome Performance 在 FP 之后的详情截图

有图中看出大工作别离是

  1. sessions 接口申请后的逻辑工作
  2. play/init 接口申请后的逻辑工作
  3. session_events 接口申请后的逻辑工作
  4. 执行 play 办法

网络申请耗时最长的是

  1. 事件流接口(session_events)
  2. 播放初始数据接口(play/init)

联合代码流程图和 Performance 截图,最初总结下以后存在问题:

  • session_events 接口(事件流)以后为异步执行,有可能会呈现晚于视频播放的状况,不合乎产品需要
  • session_events 接口自身存在数据耦合度太大导致下载工夫慢的问题(须要和后端沟通计划)
  • sessions 接口(会话列表)没必要做为前置条件,当初之所以前置是因为其余接口依赖 sessionId,但 获取 sessionId 和 sessions 接口其实没有强关联关系

    • 内部进入状况下,能够间接从 url 参数获取 sessionId
    • 外部切换的状况下,能够间接获取 sessionId
  • session 接口(会话详情)在以后环境下只提供老版本视频资源 url,和 play/init 性能反复
  • sources 接口和 paly/init 接口只依赖于 sessionId,没必要后置
  • 拿到接口数据后的工作过大,耗时重大,因为播放前所有工作都必须执行结束,因而异步并不能解决问题

优化计划

  1. 干掉 session 接口(会话详情),资源 url 对立放到 paly/init 接口,缩小网络申请(须要后端配合)
  2. 并行执行 sessions、sources、session_events 和 paly/init 四个接口,缩小互相不必要的期待
  3. session_events 接口变为两个

    • 第一个只获取题目信息缩小资源下载工夫,另一个获取全量数据(须要反对分页),播放前只通过第一个接口,加载题目信息
    • 第二个接口异步申请全副数据存储到内存,用户开展的时读取,如果用户点击开展的时候全量数据还没有返回,则依据点击项的索引分页申请对应的数据之后再开展,此时全量数据过去后须要有去重策略
  4. 应用 Web Worker 将拿到数据之后的耗时工作丢到子线程中,并行执行
  5. 调度工作 + 工夫切片

    • 给不同的任务分配优先级,而后将一段长工作切片
    • 尽量保障重要工作优先执行,其余工作或者无依赖关系工作主要执行(播放次要工作之外的其余工作)
  6. 事件流采纳虚构列表技术,缩小渲染耗费(不仅仅解决首次渲染问题,还解决后续滚动性能问题)
  7. 减少缓存,采纳 Service Worker 技术,缓存接口申请,谷歌的 Workbox 类库,以后版本只缓存 sources、paly/init 和 session_events 三个接口和局部动态资源,后续逐渐开展至全站缓存

ps:现阶段缓存曾经增加结束,产出 前端缓存机制晋升网站性能 – Service Worker

最终流程图

正文完
 0