首屏加载从11s到1s,详解前端性能优化

作者:夜雪暮歌

https://juejin.cn/post/6949896020788690958

全文共6511字/词,阅读大概需要13分钟,太长不看党请直接移步??「开始优化」部分直接查看优化手段

daf5d166d5dc454f78144056e8758e47.png

Network

Slow3G条件下22-25s加载完成

fbe4ee16b54499537d9bee1292612bcc.png

hiper

关于性能优化

在开始之前,我们需要明白一个原则:性能优化的最终目的是提升用户体验
简而言之就是让用户感觉这个网站很「快」(至少不慢hh),这里的「快」有两种,一种是「真的快」一种是「觉得快」

  • 「真的快」:可以客观衡量的指标,像网页访问时间、交互响应时间、跳转页面时间

  • 「觉得快」:用户主观感知的性能,通过视觉引导等手段转移用户对等待时间的关注

做好这两方面都能提升用户对网站的性能评价。

权衡取舍

另外就是软件工程没有银弹,一种优化方案可能适用于大多数项目,但是某些特殊情况下很可能会起反效果。

举个??,由于浏览器有单域名下并发请求限制,通常我们会将依赖统一打成一个vendor包(vue-cli默认策略),减少首屏请求数,且依赖不变动的情况下文件指纹不变,可以有效利用304缓存。在依赖不多的情况这么处理确实有助于提升加载速度,但一旦依赖多起来,vendor就会特别的大,在弱网条件下,会严重拖慢页面显示。这显然不是我们想要的,所以我们根据情况会对vendor进行拆分,比如拆分到CDN,或者直接拆分到页面中

因此,我们在做性能优化过程中,必须根据最终能给用户体验带来的提升权衡后做出适合当前项目的选择

指标和目标

目标会影响我们在过程中的决策
指标则用来度量我们的目标

目标

首先我们需要确定目标,根据场景和项目复杂度不同,制定的目标也不同,比如希望比竞品快20%,或者符合标准的”2-5-10″原则等等

这里我定下的目标是

  • 正常网速下,2s内加载完成

  • 弱网下,30s内加载完成

指标

关于指标这块,简单介绍下常见指标

  • FCP(First Contentful Paint):白屏时间(第一个文本绘制时间)

  • Speed Index:首屏时间

  • TTI(Time To Interactive): 第一次可交互的时间

  • lighthouse score(performance):Chrome浏览器审查工具性能评分(也可以npm install -g lighthouse,编程式调用)

调试工具

通过性能调试工具可以直观便捷地获取这些指标,比如Newwork、k6、hiper、Lighthouse…。具体可以看我关于性能调试工具的另一篇文章

瓶颈分析

Network分析

195fc71cd155ecc5fd3ab99ce95a0c1d.png

优化前Lighthouse

Performance分析

由于本次不涉及到应用内场景性能优化,Performance分析跳过…

dist目录分析

  • 整体体积太大,近5M

  • 出现了若干不应出现的静态资源,比如页面上没引用到SVG图标、应该被内联的小图等

  • 部分图片资源较大,最大的达到仅400KB

Webpack Bundle分析

首屏加载从11s到1s,详解前端性能优化
  1. install或build时如果出现imagemin库下载失败,可以尝试 换源、配置github hosts、install时添加解决

  2. 由于在图片下载后已经手动用在线工具压缩过,这部分提升不大

before:4.12M after:4.00M

?使用webP图片

内容(点击展开/收起)

webP是谷歌推出的新图片格式(2010),同等质量下体积拳打png脚踢jpg,目前兼容性[1]还算可以,就苹果家的表现不太理想

转换为webP图片

可以手动,也可以加入构建自动化生成。

  • 手动,可以使用webP-converter、智图等工具,但建议使用官方webP-converter,除了便捷性,同质量下体积各方面均优于智图。

  • 自动化生成,可以使用image-min-webp或其他webpack插件

页面中使用(兼容低版本)

  • HTML中使用,标签兼容

  • CSS中使用,需要配合JS做判断

  1. 请务必使用原图进行webp转换,否则会影响体积

  2. 项目大图不多,最大400KB的图片转换后只有48.9KB

?优化SVG图标

内容(点击展开/收起)

这一步我们来优化部分冗余的旧SVG图标被打包进去的情况,一般项目中SVG使用方式都是在iconfont生成JS然后引入。这种做法

  • 不直观,每次都得去iconfont复制名称使用

  • 每次增删改图标需要重新替换整个JS

  • 不能按需加载,没使用到的也会一起打包,特别是UI换图标时一般不会将旧图标删除….

  • 添加自定义SVG不友善,必须上传iconfont添加到一起再下载

更优的SVG玩法

  • 新增/修改图标

    • 在iconfont下载UI上传或者其他地方找的任意SVG图标放入icons/svg/下

    • 页面中使用全局svg组件,传入复制下SVG的文件名即可

  • 删除

    • 只需要去掉使用的地方,然后删除对应图标即可

要实现上述效果,只需要

  • 引入svg-sprite-loader

  • 创建src/icons/svg并将图标放进去,并通过webpack的require.context自动导入

  • 创建全局组件ca-svg

压缩优化

SVG通常会有一些冗余信息导致影响体积,这里我们可以使用svgo-loader来进一步压缩

?优化Ant-design-vue体积

内容(点击展开/收起)

可以看到这部分在chunk-vendor中占的比例不小

按需引入

这部分实际上已经是做了处理的了,具体操作参考ant-design-vue文档,按说明做没啥大坑,效果也符合预期。

快速上手 – Ant Design Vue[2]

删除冗余组件

部分组件是不经常用的,但却使用了Vue.use()全局引入了。这里去掉不常用和没用到的全局引入,改为页面内import()引入

?优化Ant-design-icon体积

内容(点击展开/收起)

这一部分,由于我们在项目中只使用了几个Ant内置图标,不可能有530+KB。根据Ant文档的描述是由于其将ICON全量引入的关系导致的,说法是当前用法如果按需加载的话无法确定使用者会不会在运行时改变icon,比如配置的ICON。

重定向到本地来控制

这个问题,在React版的Ant-Design是已经是做了处理的了(写法上有所调整),但在Ant-Design-Vue-1.x中仍然没有官方解决方案。目前了解到的有两种方案

  • 使用webpack-ant-icon-loader[3] (异步加载)

  • 重定向到本地文件来控制 (推荐),使用alia将将指向项目中的,然后在antd-icon来源:程序员黑叔

    声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年11月26日
下一篇 2021年11月26日

相关推荐