课程介绍
高性能极致用户体验前端开发实战课程适合所有前端开发学习或者从业者,结合目前前端开发的最佳实践,提供前端网页性能分析优化知识,结合实际项目经验分析可以采用的优化思路,并给出开发高性能极致体验网页的通用方法和技巧。 课程官方博客:前端学堂
在开始学习本课程之前,先提2个基本要求:
了解业务
作为一名合格的前端开发,我们的开发工作不是盲目的,我们的优化目标需要明确,所以首先要了解你所做的业务。不仅要知道整个业务背景,还需要了解业务需求,业务目的,最后最好能拿到业务结果。
了解业务的目的是能让你更好的分配开发的权重,合理安排开发的重点。比如开发的是视频类网站,那么开发的重点自然在于播放器加载和流畅播放以及降级方案。如果是天气类业务,那么核心业务是要保障稳定快速的展示出天气相关数据,然后是加载展示其他内容。如果是博文类网站,那么重点在于首屏的信息加载和展示。
了解用户
了解用户也是至关重要,如果连自己所做业务的受众都不知道,那么何谈用户体验,何谈极致性能? 这一部分至少你要知道现在做的业务主要是面向PC用户还是移动web用户,PC用户所用的浏览器都是什么版本,比例分布是怎样?移动端用户android和ios比例多少,各自平台版本分布情况如何?这是最基本的要求,因为我们开发的代码是在这些平台运行的。 如果不知道怎么办?没关系,从今天开始统计起来,做个埋点日志服务,前端写个脚本上报下useragent就可以了。
- navigator.userAgent
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
课程大纲
- 评判标准
- RAIL评估模型
- 性能指标
- 体验指标
- 指标数据采集
- 优化实战
- 链路优化
- 编程优化
- 链路优化
- 链路阶段分析
- 阶段指标数据
- 各阶段优化手段
- 案例分析和常用工具
- 编程优化
- 首屏渲染
- 懒加载功能组件
- 滚动加载分页组件
- web worker计算
- Task切分
- 代码分割与打包
- 前端开发架构优化
- 前端开发架构优化
- ES6 module+template
- web component
- 轻react或vue
- 微前端架构
课程官方博客:前端学堂
视频教程:云课堂视频课程
评判标准
无规矩不成方圆,所以这里先说说评判标准。评判标准主要指的是用户打开网页、浏览网页的体验和感受。我们需要一种客观的评估模型来统一量化用户体验的各个环节,这样才能找到需要优化的方向,找到开发极致用户体验网页的捷径。
RAIL评估模型
RAIL 是一种以用户为中心的性能模型。每个网络应用均具有与其生命周期有关的四个不同方面,且这些方面以不同的方式影响着性能。以用户为中心;最终目标不仅是让您的网站在任何特定设备上都能运行很快,而是使用户满意。
- Response,立即响应用户;在 100 毫秒以内确认用户输入,超过100ms建议加上动效或者loading,通过视觉冲击减少用户等待的焦虑。
- Animation,设置动画或滚动时,在 10 毫秒以内生成帧。
- Idle,最大程度增加主线程的空闲时间。主线程空闲才能随时都可以及时响应。
- Load,持续吸引用户;在 1000 毫秒以内呈现交互内容。
让用户成为您的性能工作的中心。用户花在网站上的大多数时间不是等待加载,而是在使用时等待响应。了解用户如何评价性能延迟:
延迟与用户反应 | |
---|---|
0 – 16 毫秒 | 流畅;人们特别擅长跟踪运动,如果动画不流畅,他们就会对运动心生反感。 用户可以感知每秒渲染 60 帧的平滑动画转场。也就是每帧 16 毫秒(包括浏览器将新帧绘制到屏幕上所需的时间),留给应用大约 10 毫秒的时间来生成一帧。 |
0 – 100 毫秒 | 快,在此时间窗口内响应用户操作,他们会觉得可以立即获得结果。时间再长,操作与反应之间的连接就会中断。 |
100 – 300 毫秒 | 可感觉慢,需要loading,用户会遇到轻微可觉察的延迟。 |
300 – 1000 毫秒 | 慢,需要做loading和占位。在此窗口内,延迟感觉像是任务自然和持续发展的一部分。对于网络上的大多数用户,加载页面或更改视图代表着一个任务。 |
1000+ 毫秒 | 很慢,超过 1 秒,用户的注意力将离开他们正在执行的任务。 |
10,000+ 毫秒 | 放弃,用户感到失望,可能会放弃任务;之后他们或许不会再回来。 |
响应:在 100 毫秒以内响应
在用户注意到滞后之前您有 100 毫秒的时间可以响应用户输入。这适用于大多数输入,不管他们是在点击按钮、切换表单控件还是启动动画。但不适用于触摸拖动或滚动。 如果您未响应,操作与反应之间的连接就会中断。用户会注意到。 尽管很明显应立即响应用户的操作,但这并不总是正确的做法。使用此 100 毫秒窗口执行其他开销大的工作,但需要谨慎,以免妨碍用户。如果可能,请在后台执行工作。 对于需要超过 500 毫秒才能完成的操作,请始终提供反馈机制,比如loading,进度条等。
动画:在 10 毫秒内生成一帧
动画不只是奇特的 UI 效果。例如,滚动和触摸拖动就是动画类型。 如果动画帧率发生变化,您的用户确实会注意到。您的目标就是每秒生成 60 帧,每一帧必须完成以下所有步骤:
从纯粹的数学角度而言,每帧的预算约为 16 毫秒(1000 毫秒 / 60 帧 = 16.66 毫秒/帧)。 但因为浏览器需要花费时间将新帧绘制到屏幕上,只有 10 毫秒来执行代码。 在像动画一样的高压点中,关键是不论能不能做,什么都不要做,做最少的工作。 如果可能,请利用 100 毫秒响应预先计算开销大的工作,这样您就可以尽可能增加实现 60fps 的可能性。 如需了解详细信息,请参阅渲染性能。
空闲:最大程度增加空闲时间
利用空闲时间完成推迟的工作。例如,尽可能减少预加载数据,以便您的应用快速加载,并利用空闲时间加载剩余数据。 推迟的工作应分成每个耗时约 50 毫秒的多个块。如果用户开始交互,优先级最高的事项是响应用户。
要实现小于 100 毫秒的响应,应用必须在每 50 毫秒内将控制权返回给主线程,这样应用就可以执行其像素管道、对用户输入作出反应,等等。以 50 毫秒块工作既可以完成任务,又能确保及时的响应。
加载:在 1000 毫秒以内呈现内容
在 1 秒钟内加载您的网站。否则,用户的注意力会分散,他们处理任务的感觉会中断。侧重于优化关键渲染路径以取消阻止渲染。 实际操作中,我们无需在 1 秒内加载所有内容以产生完整加载的感觉,而是启用渐进式渲染和在后台执行一些工作,默认只加载和渲染首屏内容,将非首屏、非必需的加载推迟到空闲时间段处理。
关键 RAIL 指标汇总
要根据 RAIL 指标评估您的网站,请使用 Chrome DevTools Timeline 工具记录用户操作。然后根据这些关键 RAIL 指标检查 Timeline 中的记录时间。
RAIL 步骤 | 关键指标 | 用户操作 |
---|---|---|
响应 | 输入延迟时间(从点按到绘制)小于 100 毫秒。 | 用户点按按钮(例如打开导航)。 |
动画 | 每个帧的工作(从 JS 到绘制)完成时间小于 16 毫秒。 | 用户滚动页面,拖动手指(例如,打开菜单)或看到动画。 拖动时,应用的响应与手指位置有关(例如,拉动刷新、滑动轮播)。 此指标仅适用于拖动的持续阶段,不适用于开始阶段。 |
空闲 | 主线程 JS 工作分成不大于 50 毫秒的块。 | 用户没有与页面交互,但主线程应足够用于处理下一个用户输入。 |
加载 | 页面可以在 1000 毫秒内就绪。 | 用户加载页面并看到关键路径内容。 |
这是Google工程师提出来的RAIL优化模型,在实际前端业务监控中,我们可以拆分成更多的数据指标进行统计分析。
性能和体验数据指标
数据驱动业务开发,我们的目标是高性能和极致用户体验,那么我们首先需要制定符合我们目标的性能数据指标和体验数据指标。 在制定数据指标之前,我们分析下页面加载过程,我们分为这四个部分:
用户体验 | 描述 |
---|---|
它在发生吗?happening | 网页浏览顺利开始了吗?服务端有响应吗? |
它是否有用?useful | 用户是否能看到足够的内容? |
它是否可用?usable | 用户是否可以和页面交互,还是页面仍在忙于加载? |
它是否令人愉快的?idle | 交互是否流程和自然,没有卡段或闪烁? |
性能指标:加载呈现又快又稳。加载到展现的性能指标和稳定性指标。
体验指标:操作反应灵敏。点击,滑动等交互响应及时,操作流畅,动画运行流畅。
- 秒开率:页面首屏加载时间小于1s的比例,也就是页面加载到onload事件触发时所消耗的时间。
- FP(first paint) 和 FCP(first content paint) 分别是指页面首次绘制和首次内容绘制。FP(首次绘制)包括了任何用户自定义的背景绘制,它是首先将像素绘制到屏幕的时刻。FCP(首次内容绘制)是浏览器将第一个 DOM 渲染到屏幕的时间。该指标报告了浏览器首次呈现任何文本、图像、画布或者 SVG 的时间。这两个指标其实指示了我们通常所说的白屏时间。
- FMP(first meaningful paint)首次有意义绘制, 是页面可用性的度量标准。因为很难有一个通用标准来指示所有的页面当前时刻的渲染达是否到了有用的程度,所以当前并没有制定标准。对于开发者,我们可以根据自己的页面来确定那一部分是最重要的,然后度量这部分渲染出的时间作为FMP。
- TTFB(time to first byte, 首字节时间),是指从浏览器发起第一个请求到数据返回第一个字节所消耗的时间,这个时间包含了网络时间,后端处理时间等等,可以作为一个链路数据综合参考指标。
稳定性指标
- 资源错误:静态资源加载错误,常见的就是404,资源地址不正确或者远程服务有问题。
- JS报错:页面运行时抛出来的异常信息。比如变量未定义,函数报错等等。
- Crash:页面白屏不展示内容,很可能是页面某个模块报错导致整个页面不展示。
- 内存堆栈:监控页面内存和堆栈使用情况,常见如页面内存泄露等原因会直接导致APP闪退。
- 接口报错:接口挂了,请求超时。或者接口返回了错误信息。或者接口返回数据错误,比如空数据,不符合预期。
- 交互延迟:用户点击后页面没有响应或者响应时间超过100ms,用户感觉这次点击操作是延迟的(可称为无效点击)。通过EventTiming API我们可以统计用户交互操作后的浏览器响应时间。
- 卡顿:统计浏览器中执行时间超过 50 ms 的任务,都是 long task(Long tasks API ),可能会造成页面卡顿。
- 滚动流畅性:滚动过程是否流畅,监测用户开始操作到页面开始滚动的时间差,按照前面的标准,小于100ms才会体验流畅。
- 动画流畅性:监测动画开始到动画结束,计算帧率FPS。按照前面的标准,每帧计算时间小于10ms才会体验流畅。
- TTI(time to interactive, 可交互时间):指页面已渲染出内容,同时可以响应用户的输入的时间。
- FID(First Input Delay),首次输入延迟,从用户看到页面到第一次输入的延迟,一般都是因为主线程阻塞,会导致响应慢。这个指标反映用户对当前页面的第一感觉,如果用户很久没有交互,说明首屏内容比较吸引人,或者用户很快就切走了,说明对用户没有吸引力。
性能指标数据采集
介绍上面我们总结的性能和体验指标如何准确有效的采集。
优化实战
我们已经全面分析总结了评估页面性能和用户体验的各个指标参数。那么怎么来优化呢?open signal官方提供了2018年2月份统计的全世界4G网络覆盖率和通信速率的统计分布图如下,在目前移动互联网的浪潮下,我们要利用好用户终端设备的每个字节的流量。
当然页面性能和体验优化并不是一蹴而就的,需要不断的研究、跟踪,发现问题,解决问题。但是我们可以在一开始编写业务代码的时候就做的更好,做到极致。所以,关于优化实战我们主要分为两部分:加载渲染链路优化 和 编程代码优化。
加载渲染链路优化
从访问url到页面呈现,整个加载和渲染链路可以做优化的思路。
加载链路:浏览器导航开始->检查缓存->DNS->HTTP->解析
渲染链路:浏览器内核或者webview(对于ios区分wkwebview和早期版本的uiwebview)渲染流程
具体详情参看下面这篇文章:
编程代码优化
我们说的“快”,并不仅仅指浏览器器加载页面快,就是常说的秒开率,一般指DomContentLoad时间。但是“快”其实包含更多的含义,除了前面说的浏览器加载快,还包含浏览器解析快(Javascript脚本发布时通常都会做代码压缩混淆,不仅是减少体积,也为了安全性),JS脚本编译快(我们知道javascript在浏览器的javascript虚拟机【managed runtime environment for JavaScript,JavaScript托管运行时环境】中运行的,所以也需要编辑JS脚本成字节码,才能运行),最后一个就是javascript执行快。
链路优化中,我们已经解决了JavaScript下载加速的问题,那么剩下的优化工作主要集中在优化浏览器解析、编译并执行JS脚本。影响浏览器解析和执行JS脚本的因素主要是JS脚本的体积大小和代码的复杂程度。所以编程代码优化实践主要是减少代码的体积和按需降低代码复杂度,实现浏览器解析快,JS脚本编译快。
- 代码体积大,加载就会耗时,而且占用cdn存储资源和http请求资源,浏览器解析时暂用内存多,分析代码耗时。
- 代码复杂度高,代码解析就比较耗时。如果依赖一些复杂的类库,还要考虑库的解析和执行时间。浏览器解析代码会占用更多内存,使用堆栈更深,执行耗时。
优化策略:
- 首屏渲染与PRPL
- 懒加载组件
- 滚动加载分页组件
- web worker
- task拆分
- 代码分割与打包
- 项目架构优化
具体详情参看下面这篇文章:前端极致性能体验编码框架优化
参考
- Can You Afford It?: Real-world Web Performance Budgets
- Progressive Performance
- Reducing JavaScript payloads with Tree-shaking
- Ouch, your JavaScript hurts!
- Fast & Resilient — Why carving out the “fast” path isn’t enough
- Web performance optimization with Webpack
- JavaScript Start-up Optimization
- The Impact Of Page Weight On Load Time
- Beyond The Bubble — Real-world Performance
- How To Think About Speed Tools
- Thinking PRPL
- navigation-timing
- the-cost-of-javascript
- learning-and-using-the-user-timing-api