前言
关于耗时:
-
首屏耗时与用户设备、所在网络环境、程序代码有很大关系。线上环境有2/3的运气成分。
-
理论上相同地域访问 https 比访问 ip 慢,但小程序要求必须使用 https。
-
小程序启动时由微信加载代码包,与服务域名无关,进入页面后才会发起首次网络请求,某些用户环境出现 ERR_CONNECTION_RESET,导致上报的 API 接口及首屏耗时因网络不通畅爆表。
-- 小白记 于2021年12月
前端性能监控(RUM) 接入
:
RUM 是腾讯提供的一款前端监控方案,只需在控制台上创建业务系统和应用,获取上报 ID;通过安装 npm 依赖配置 JSON 就可以实现测速和日志的收集。
-
-
-
-
-
-
-
-
-
-
-
-
// 在应用支持 NPM 时使用 NPM 安装 Aegis SDK。 // npm install --save aegis-mp-sdk
// 引入后进行初始化 import Aegis from 'aegis-mp-sdk';
const aegis = new Aegis({ id: 'xxxx', // 上报 id uin: 'xxx', // 用户唯一 ID(可选) reportApiSpeed: true, // 接口测速 spa: true // spa 应用页面跳转的时候开启 pv 计算 });
注意:
- 在小程序中,要按照小程序规则开启 NPM 构建。
- 必须将 https://aegis.qq.com 添加到 request 合法域名中,否则 RUM 控制台中没有正式版本的数据。一般会在 devTools 中开启忽略合法域名校验,为了方便开发调试调用开发环境,而忽略这个配置。
数据分析
:
在 RUM 控制台-性能页面,列出了时间段内每个页面的页面首次渲染时间,也提供了不同维度的数据统计,如地域、网络、机型等,接下来需要从页面中分析出耗时较大且访问较为频繁的页面进行优化。
通过按耗时和按采样量排序,很明显下图1,3,4 这三个页面拉高了用户的等待时间,是主要考虑优化的页面。
[点击查看大图]
页面具体分析
:
上图的页面都包含网络请求,并在请求结束后通过 setData 触发页面的 DOM 更新,此外:
- 第一个页面是小程序的首页,包含广告组件和自定义的记录预测卡片的列表。
- 第三个页面含有自定义的日历组件和日常备忘卡片列表。
- 第四个页面包含广告组件和互联网图片资源。
该如何进行分析,优化呢?
首屏优化分析
:
提高网页的性能一般要包括优化加载的速度和程序执行的流畅度;而加载速度又可以优化服务端响应的时间(包括代码包的下载时间,网络请求接口的响应时间,互联网的图片及字体等资源文件)和页面自身加载和渲染的时间。
图片资源
常见图片可以采用JPG
、PNG
、WEBP
、雪碧图或字体图标实现,可搜索到的描述大概都是不同格式适用的不同场景,以及从占用带宽上的描述。
- 首先要选择合适的图片格式
- 照片图片使用 webP。
- 复杂的图形使用 PNG 或 JPG,看哪个格式的文件小。
- 有透明度的图形使用 PNG 或 webP。
- 可能缩放的图形、图标等使用 SVG。
- 动态图尽量不使用 GIF,无法使用 CSS 的用视频替代。
- 在小程序中,只有网络图片且在基础库高于 2.9.0 的微信上可以使用 webp ,目前绝大多数的微信用户基础库以及高于 2.16.0版本库,因此可以对互联网图片转换为 webp 格式,减小网络加载耗时。
- 目前没有查到关于这几种方式显示图片资源的页面渲染耗时分析。
网络分析优化
通过RUM 控制台中的 API 监控页面,可以发现从微信小程序中检测到的网络请求耗时波动很大,分布在100ms - 4000ms 。
[点击查看大图]
进入 nginx 筛选出对应时间段的网络请求,按照 $upstream_response_time
分组计数如图,发现服务器端接口性能比较稳定。问题应该出现在客户端网络到服务端中间的网络上。
[点击查看大图]
小程序中强制要求使用 https 协议发起网络请求,请求链路为 DNS -> Connect -> SSL -> request -> response ,在本机调试各阶段起止时间戳及耗时如下:(数据只代表本机网络情况,结果可能存在波动)。可见小程序在发起第二次请求时,已经将 DNS 等信息缓存,并重用了 Socket 链路,从客户端到动态加速网络之间的耗时大概在 40ms,从动态加速网络到服务器耗时大概在 20ms。而在第一次请求中,客户端需要进行 DNS 解析,建立 SSL 链路增加了网络耗时。
JS 优化
- 首先排查在主线程上不要使用同步方法,减小主线程阻塞。
- 开启小程序中的代码按需注入,避免没有使用的代码注入到小程序运行环境中,影响注入耗时和内存占用。
-
-
-
{ "lazyCodeLoading": "requiredComponents" }
- 生产环境去掉不必要的日志打印
-
-
-
/** @const */ var LOG = false; LOG && log('hello world !');
CSS 优化
因为构建 CSSOM 树时会阻塞页面的解析,因此需要:
- 删除没有使用的 CSS 代码
- 减小 CSS 文件大小,如 #FFFFFF -> #FFF , 0px -> 0,不要使用 Base64 编码的图片。
优化历程
:
资源优化
-
按照页面访问的频次,将图片资源分成常用的和不常用的,将常用的放入小程序代码包通过本地加载,将不常用的转换成 webp 放到服务器。
-
减小代码包体积:压缩代码包中的图片资源,对 PNG 格式的透明图设置更少的颜色数;通过依赖分析,更换体积更小的 markdown 渲染依赖。从 1M+下降到280K+。
网络优化
-
由于只有一台华北地区的服务器,为解决不同地域和运营商的访问速度,开启全站动态加速。通过某测速网站看到可解析到70+个独立 IP,并且不同地区的用户会访问到同运营商较近的 IP,然后由 DCDN 通过内部线路转发用户到服务器的请求。
-
通过分析,首次请求时需要进行域名的解析和建连,后续的请求会复用该链路,解析和 SSL 等时间为0。通过某测速网站可看到平均响应时间在 0.3s,考虑到链路复用,网络请求时间会在 60ms 左右。
-
对不经常变更且频繁访问的接口,在 DCDN 中设置静态缓存,并触发接口预热,将接口的响应缓存到 DCDN 的二级节点上。这样用户发起这些请求时,直接由 DCDN 做出应答而不回源到真实服务器处理。
-
在服务端和客户端开启 http/2 协议支持。由于小程序中无高并发请求,自测没有明显改善。
-
对超过 1kb 的响应体开启 gzip 压缩。
-
对服务端的图片等静态资源设置浏览器缓存。
-
由于小程序不像 BAT 这么大用户量和高频的访问,根据 DNS 的解析机制,各地运营商如果有缓存 DNS的解析结果就不会向跟 DNS 进行解析,利用网站测速提供的服务,发送 GET 测速,让各地运营商缓存 DNS 结果。
-
开启 OCSP Stapling,提高证书的校验性能。
-
小程序使用中,服务端会调用 api.weixin.qq.com 换取用户的 openid,通过调用微信公众平台接口获取该域名的各个 ip 地址,在服务器执行 ping 命令,找到最快的一个ip,写入host文件。从 40ms 降低到 28.8ms。
代码编写
-
代码中对图片标签开启懒加载。
-
减小冗余的
层次嵌套。 -
为 data 赋初始值,避免在网络请求结束后赋值引起页面元素的位置变动。
-
开启代码的按需注入
-
采用 DCDN 后,各地域各运营商的绝大部分网络请求会在 0.3s 内到达,因此删除了网络请求起止的 loading 浮层动画。
-
原来为了真机调试方便,把网络请求、自定义组件的响应等打印到了 vConsole 中。目前线上生产环境删除了所有的日志打印。
-
删除了部分无用的 css 代码。优化的部分 css 样式的选择器。
-
将网络请求从 onReady 提前到 onLoad 。
-
亲测使用骨架屏只会让人感觉页面非白屏了,但会增加首屏的时间。
业务逻辑
-
所有新用户(首次访问)最初进入小程序时,页面和 data 中的数据都是一样的。将这些数据作为 data 的默认值,直接显示出来,网络请求到达后,由于 data 内容不变,不会发生页面的重新渲染。
-
用户使用程序后,将从网络请求中获取的用户数据存储到 storage 中。
-
在服务端,当小程序用户登入后,开启异步线程将主要的用户数据从 My SQL 刷入 Redis 进行热备。
-
对于长列表改为数据分页加载。
优化效果
:
如下图腾讯云前端性能监控显示大部分地域首屏耗时在 0-0.5s 之间:
[RUM 首屏耗时截图]
[某测速网站 DCDN 截图]
上述首屏耗时优化效果最终评估平台为:腾讯云前端性能监控。点击文末「阅读原文」了解腾讯云前端性能监控。
联系我们
扫码加云监控小助手,回复“Rum”
加入前端性能监控技术交流群
RUM 相关文章:
关注我们,了解腾讯云监控的最新动态
本文转载于腾讯云+社区,原文链接: