什么是性能
我理解的就是满足用户体验,在最优的时间能让用户看到页面内容,留住用户。
前序---js在网页端的执行环境-浏览器
参考:https://www.jianshu.com/p/33f1c67bf381
一、页面性能的衡量的辅助工具-- Performance Timing Api
浏览器提供了一些能力让我们做性能优化,判断页面的性能好坏,它的关键是每个关键节点的事件回调,在回调中可以打印时间戳。根据相关标准或者公司规定找到优化点。
先了解浏览器运行过程中与性能关乎的几个大部分
Navigation Timing Api
1. navigationStart 从上一个页面开始要进行跳转的最初钩子
2. unloadEventStart / End 表示前一个页面unload的时间点
3. redirectStart / End 页面重定向发生的事件开始 & 结束
4.fetchStart / End 浏览器准备好用http请求抓取文档的时间(准备时间)
5. domainLookupStart / End http开始/重新建立连接的时间
问题:如果是长连接,需要从哪个时间段获取当前建立时间,长连接是持久不会中断的链接,长连接的结束是抓取文档结束
不同版本的http协议,对于tcp 的兼容性或者实现方式不同 1.0 是一次请求建立一次TCP链接,1.1建立一次TCP链接可以复用, 2.0 可以多帧传递,将一次请求分为多帧,按照帧结构发送数据
6. connectStart / End 开始链接的时间
所有跟前后端相关的都在这个阶段,自己包含前后端,纯数据链接的事情
7. secureConnectionStart / End http加密通路开始的时间和结束的时间
8. requestStart / End 请求花费的时间
9. responseStart / End 返回花费的时间
10. domLoading (loading interactive ready三合一 )
开始渲染dom树的时间
和它对应的还有domInteractive,代表完成dom解析的时间
domContentEventStart / End 代表dom解析完成后,网页内部资源开始加载和结束时间
domComplete代表dom解析完成
11. loadEventStart / End 代表load事件回调函数执行完毕的点
使用:
// index.html<script>
javascript:(() => {
var perfData = window.performance.timing
var pageLoadTime = perfData.loadEventEnd - perfData.navigationStart
console.log('页面加载耗时', pageLoadTime,‘ms’)
})()
</script>
问题汇总
如何建立一个长连接
1、建立一个websoket
一定要记得销毁
2、开启一个keep-alive,与后台沟通好,某一次请求是keep-alive的长连接,这个请求一定会等到后台或者网关、中间层等返回超时才会断掉,不然会一直等到链接有返回udp:发布消息,不确定一定会受到
tcp:发布消息有回应,三次握手http与https的区别
单页面有重定向吗?没有
单页面路由应用内部是前端内部自己控制的单个组件之间的路转,不会经过performance navigation timing api的阶段。
单页应用的app实例是不会被销毁的,可以在路由导航守卫里去时间戳的差加载页面时,载入条从0到100发生了社么?
载入条从加载到加载满不包含dom渲染。从重排之后,开始渲染的时候就加载完了。(这才引深了要不要加载骨架屏、loading框等,loading框本身也是dom)。载入条完成代表页面组织好,重排好,开始渲染了。为什么有的页面载入条加载完了,页面依然没内容?
因为渲染可能依赖其他因素,比如说v-if,有逻辑被padding住了, js线程堵塞了dom渲染只要用浏览器就可以使用这些api,单页面用不到这些api,单页面只有一个页面,是通过路由切换页面,可以在代码里打印出来的,没必要用这些api
ajax的接口性能怎么拿?
ajax工具的拦截器上拿http cache
302,重定向,origin来源有个cache,来自缓存http cache + dns是一个完整的寻址过程
dns地址解析过程?
本机->路由器->供应商本地机房->区域核心机房->......->根服务器单页面加载性能、接口性能、资源性能、运行时帧数
加载性能:导航守卫
接口性能:接口工具拦截器
资源性能:
单页分两种:一种cdn远端加载一种是本地加载。
本地加载性能是把当前资源加载的时间计算出来,
cdn资源是fetch抓取文档的时间
运行帧数:loadEventEnd-loadEventStart就是window.load回调函数执行时间
浏览器是从dominteractive这个时间点开始第一次“事件循环”的吗?
二、 页面性能的核心指标
标准:谷歌提出的网页性能的核心指标-core web vitals,可衡量的,并且反应真实体验:加载、交互、视觉稳定性
1、LCP(largest contentful paint)最大内容渲染
衡量页面的装载性能,前2.5s内进行最大内容的渲染。
a. 最大内容包含什么?
-<img>元素
-<svg>元素
-<video>元素
-通过url加载的背景图片
-包含了文本节点或其他内联文元素的块级元素b.LCP值低下的原因
-服务响应慢
-阻断渲染的js和css
-资源的加载
-项目的渲染c. 针对改造(优化)
-缓存 离线页面、请求内容的缓存、资源缓存=>减少服务的请求 | 减少服务的查询=>强缓存、协商缓存 | 缓存机制渲染的阻断:css | js进行压缩、合并、内联;后置js逻辑
对于文件的优化=>对于格式的优化 转化图片的格式为JPG或者webp=>图片格式 =>加载和显示 | 云资源管理
工程化:打包优化-压缩、分片、异步、懒加载
框架层面-首屏加载问题,拆分、异步模块、统一封装
写法-减少网络请求、及时清理垃圾cdn怎么找到最近的节点的?
主要的路径访问的是主路径的服务,静态资源经过统一的cdn服务商,服务商分发具体的ip,在找ip的时候就找过去了
cdn缓存,有时需要手动更新
2、FID(first iput delay)第一次输入延迟
页面首页输入延迟应该小于100ms
衡量交互
造成FID的原因:
a. js执行时间过长
-缩小压缩js文件
-延迟加载不要的js逻辑
-尽量减少未使用的ployfill(新的api让任何版本浏览器都兼容)
b. 分解耗时任务
-50ms长任务 (比如提交表单,不要提交时才提示,不能提交就不给表单权限)
- 长任务拆分成前置、后置或者多个短任务
c. workers
通过woker提高执行效率,并实时同步
3、CLS (cumulative layout shift)页面布局变化的频率
衡量视觉稳定性
元素布局移动可能发生的位置偏移量
a. 不使用无尺寸元素
比如:图片,外边框有宽高
b. 减少内部内容的插入
插入内容把高度预留好,减少抖动
c. 字体的控制,默认字体为先=>本地替换字体=>加载字体
全局字体的统一
4,其他指标
FMP:首次有意义的渲染
白屏率:白屏率指标(4s or 6s), 从用户点击之后6s后截屏,如果是白屏或者有颜色的屏幕则计入白屏率,白屏次数/总进入次数
举例:
三、性能评估神器--CWV工具-core
下载参考:https://www.chajianxw.com/developer/26697.html
指标参考:https://www.jianshu.com/p/5b6a7c947f42
四、大厂的监控体系
a)埋点上报 =>点到点上报(关心的上报)+ 信息采集汇总
b) 数据处理 =>阈值设置 / 数据分类(前端、后端、node)/ 数据重组
c) 可视化展现 =>grafana /自研报表
d) 告警处理 => 告警触发 / 触发分派 =>通过一定途径分发
未来的可能-bigpipe
本质:页面分解为若干pagelet
1、服务端接收来自客户端的http请求
2、从存储层获取数据
3、生成HTML,作为部分模块的基础
4. 浏览器回去解析内容,遗留区域作为展示面板进行客户端渲染
5、加载渲染生成
五、问题汇总
项目发布后,配置了文件名hash,不希望用户有手动刷新这个操作如何实现?
1、不刷新做到实时更新不太可能,静态资源不会主动更新
获取新资源的方式
1、通知您的当前页面页面有更新,请手动刷新。
2、页面停留或者使用超过一定时间,自动登出,要求用户重新登陆。online表单与普通表单的区别
online表单是json-sgram生成表单页面交互过程中,检测到页面js执行报错,怎么阻止页面白屏?
js报错之后已经晚了,需要做的是在渲染之后再加载js,举个例子,渲染表格在请求到数据后有3s的时间前端需要处理数据才能组装成表格数据,则我们需要把数据拉过来,mounted之后再对数据进行处理,这样页面会先渲染表格,之后再把数据填到表格。
这时会涉及到表格闪一下,则可以加loading框等iframe
父子应用的window是否是一个
父子应用是同域是window是一个,外部可以拿到内部的东西;
非同域情况,外部拿不到内部东西
只要window不一样,他们的浏览器相关的api都不一样。
六、性能优化
1、js性能优化
参考:https://csspod.com/frontend-performance-best-practices/
2、 前端框架-单页应用相关性能
(1)性能优化的目标
性能优化需要针对不同的项目,具体问题具体分析,根据性能数据分析, 定位影响加载时长的阶段,分析监控数据得出预期能优化到的目标,比如:接口如果返回数据需要1000ms,那么这个数据必然存在优化空间的,再比预取数据数据可以在init的时候调用接口,偏偏在mounted里调用,显然也存在优化空间等等,这也说明性能优化不只是前端或者后端的问题,是前后端配合或者都需要参与的工作。
(2)可优化的方面
1、整体方面
prelink:提前建立链接,提前发送预连接请求,将连接放入连接池,使用时直接拿出,节省DNS查询和建立TCP连接的时间
预请求:提前请求接口数据
预加载:提前加载js代码包
骨架屏:提升用户体验
redis缓存、数据库迁移释放空间
按需加载:https://www.cnblogs.com/ToBeBest/p/13404617.html
2、页面方面
(1)预取数据/预加载 (prefetch\preload: https://juejin.cn/post/6893681741240909832)
(2)非核心请求后置:将启动阶段的非核心请求(例如日志后置)在FMP之后被发送,减少核心请求的响应时间,设置defer: true,减少首屏数据的逻辑处理,减少setdata次数,减少http/https请求次数,雪碧图、文件压缩打包
(3)cdn缓存:静态资源缓存如(react、react-dom、axios等),异步加载 script加载 ( defer:在HTML解析完之后才会执行。如果是多个,则按照加载的顺序依次执行。async:在加载完之后立即执行。如果是多个,执行顺序和加载顺序无关。)
(4)避免组建重复打包:在webpack的config文件中,修改commonChunkPlugin的配置minChunks为2,这样就会把使用2次以上的包打包到公共文件中,避免重复加载组件。
(5)tree-shaking 删除冗余代码
(6)图片懒加载 / 图片压缩 / 小图片图文字体或者base64
(7)分屏渲染:首次进入页面只渲染可视范围的内容,首次渲染结束,再异步渲染剩下的,列表只渲染几条,列表数据可以前端拆也可以获取到的就是几条,第二屏的内容可以通过事件触发渲染(滑动页面),除了纵向,横向也可能超过一屏,例如swiper
3、第三方插件方面
框架版本升级,接入优化包(appjs 拆分,apack,css-module)
预加载/懒加载
cdn缓存
UI框架按需加载,例如:import { button } from 'elementUI'
4、打包工具,以webpack为例
减收主包体积的手段:分包减少包加载耗时
(1)动态加载路由,减少入口文件体积:es6的import()方法与webpack的require.essure()都可以根据动态加载的组件来生成单独的chunk进行分包;
框架版本升级
(2)webpack提升打包速度
1、配置 resolve.modules 减少检索路径
2、配置装载机的 include & exclude 减少目录检索范围 在使用 loader 的时候,通过指定 exclude 和 incude 选项,减少 loader 遍历的目录范围,从而加快 Webpack 编译速度。
3、使用 webpack-parallel-uglify-plugin 插件来压缩代码
4、使用 HappyPack 来加速代码构建
5、利用 DllPlugin 和 DllReferencePlugin 预编译资源模块-拆分bundles
(3)webpack优化打包的大小,减小打包体积
1、 Tree Shaking Tree Shaking 可以实现删除项目中未被引用的代码 webpack4的话,开启生产环境就会自动启动这个优化功能。
2、 splitchunkspluginwebapck4抽取公共模块“SplitChunksPlugin” commenChunkPlugin 提取公共代码组件
3、合理使用 sourceMap (去除devtool选项 )
很多教程都会教你在webpack.config.js设置devtool选项,比如:devtool:'eval-source-map'。但是这只适用于开发环境,这会导致打包的文件往往有几M,所以在生产环境必须要去除掉此配置。
把部分依赖转移到 CDN 上,避免在每次编译过程中都由 Webpack 处理,通过script加载(externals将第三方库以cdn的方式去引入 https://www.cnblogs.com/ssh-007/p/7944491.html)
4、 使用 webpack-parallel-uglify-plugin 插件来压缩代码
5、 分离css。安装插件 npm install extract-text-webpack-plugin --save
5、秒开实践
https://smartprogram.baidu.com/docs/develop/performance/experience/
6、自测数据获取方法
(1)获取方法运行时长
console.time 和 console.timeEnd
(2) 准确获取首屏加载时间
https://blog.csdn.net/qq_34595425/article/details/132725747
(3)获取首页图片的加载时长
针对某张图片:imagesloaded插件(done / fail / progress)
优化并不是一气呵成的事儿,而且随着迭代开发也会出现新的性能问题,总体来说我们可以分步骤,从整体到页面再到投放渠道逐步进行,且多方协商合作效果可能更显著
整体:前端,预加载、预链接、预请求、骨架屏
后端,缓存、数据库迁移空间释放
页面:前端,本地图片压缩、分屏数据、首页数据缓存、图片懒加载、data对象优化
后端,接口数据优化,cdn
投放渠道:集中投放时间点错开、全量加载
性能优化文档汇总:https://www.cnblogs.com/feiyu6/p/7262778.html
https://blog.csdn.net/qq_42072086/article/details/110849890
7,项目实践-bd小程序
FMP理论标准
(1)指标含义
80分位FMP
NA有意义的渲染时长(整体),正排后取80分位
计算方式:
Android:小程序启动过程中,dom tree构建时触发NA webview的layout布局,当layout布局完成后,开始渲染内容。内容渲染高度超过当前屏幕的时间。 (结束点通过T7内核domFirstScreenPaint NA回调收集)
IOS:小程序启动过程中,dom tree构建时触发NA webview的layout布局高度超过当前屏幕的时间
4s白屏率
指标含义:WebView 有意义的渲染时长超过4s的白屏比例
计算方式:WebView 的Fmp超过4s计为1次白屏pv,4s白屏率 = 白屏pv / 启动pv
6s白屏率(B端白屏)
指标含义:用户触发页面打开后,6s后仍然没有任何页面绘制,则认定为白屏
计算方式:从用户点击小程序入口开始计算时间,6s后进行截图分析。当截图为空白页面或只有背景色,则记为一次白屏
到达率
指标含义:WebView有意义渲染成功的比例
计算方式:FMP到达次数/调起次数
(2)优化目标
Android:2.2s,IOS:1.0s
(3)性能现状
我们的小程序,整体差很多,安卓 3.378s(目标2.2s),IOS 1.078s(目标1.0s)
(4)优化方案
阶段一: 整体优化;
阶段二:页面优化和渠道优化并行推进优化。高流量重点页面优先优化(流量占比1%以上);低流量和渠道推进优化
(5)优化结果
我们双端收益均相对理想:
Android :fmp80 从 3378ms → 1789ms (下降 47.04%)、4s白屏从 13.98%→ 2.81% (下降 79.90%)、6s白屏从 0.91% → 0.26% (下降71.43%)、到达率从 73.00% → 92.43% (升高26.62%)
IOS:fmp80 从1078ms → 710ms(下降 34.14%)、4s白屏从 2.72%→ 1.30% (下降 52.20%)、6s白屏从 0.94% → 0.52% (下降44.68%)、到达率从 86.02% → 97.71% (升高13.59%)
2. 优化时间关键点说明:
以Android为例进行说明。
Android 性能趋势图:
(5) 优化盘点及收益说明
在小程序上做的优化及收益,盘点如下:
(6)统计平台汇总
1. 小程序-性能统计平台:
2. showx小程序性能平台(可用于和其他小程序对比):
3. 小程序B端:
4. 前端接口时长/性能统计平台: