浅谈前端页面性能以及优化实践

什么是性能
      我理解的就是满足用户体验,在最优的时间能让用户看到页面内容,留住用户。

前序---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. 前端接口时长/性能统计平台:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335