https://maimai.cn/article/detail?fid=1773648919&efid=5xfDOW5OR3tSS0iyVW2ukA
近期,开发 C 端 h5 页面时,发现首页白屏时间比较长,并且用户也多次反映了这个问题,优化这个首屏加载时间是迟早的事,所以在开始优化前先做一些必要的知识储备~
还在看那些老掉牙的性能优化文章么?这些最新性能指标了解下
[http://juejin.cn/post/6850037270729359367#heading-0]
首次绘制,FP(First Paint),这个指标用于记录页面第一次绘制像素的时间。
首次内容绘制,FCP(First Contentful Paint),这个指标用于记录页面首次绘制文本、图片、非空白 Canvas 或 SVG 的时间。
FP 指的是绘制像素,比如说页面的背景色是灰色的,那么在显示灰色背景时就记录下了 FP 指标。但是此时 DOM 内容还没开始绘制,可能需要文件下载、解析等过程,只有当 DOM 内容发生变化才会触发,比如说渲染出了一段文字,此时就会记录下 FCP 指标。因此说我们可以把这两个指标认为是和白屏时间相关的指标,所以肯定是最快越好。
最大内容绘制,LCP(Largest Contentful Paint),用于记录视窗内最大的元素绘制的时间,该时间会随着页面渲染变化而变化,因为页面中的最大元素在渲染过程中可能会发生改变,另外该指标会在用户第一次交互后停止记录。指标变化如下图:
介绍 TTI 之前,首先要介绍一下长任务,一个任务的耗时超过 50ms,这个任务就可以被认为是长任务,用户的交互操作也是在主线程执行的,所以当发生 Long Task 时,用户的交互操作很可能无法及时执行,这时用户就会体验到卡顿(当页面响应时间超过 100ms 时,用户可以体验到卡顿)。
首次可交互时间,TTI(Time to Interactive),测量页面所有资源加载成功并能够可靠地快速响应用户输入的时间。通常是发生在页面依赖的资源已经加载完成,此时浏览器可以快速响应用户交互的时间。指标的计算过程,需要满足以下几个条件:
首次输入延迟,FID(First Input Delay),记录在 FCP 和 TTI 之间用户首次与页面交互时响应的延迟。记录第一次与页面交互到浏览器真正能够处理响应该交互的时间,这个延迟出现的原因是浏览器的主线程可能在忙于其他工作,比如解析 JS 文件等,所以无法及时响应用户。
阻塞总时间,TBT(Total Blocking Time),记录在 FCP 到 TTI 之间所有长任务的阻塞时间总和。主线程执行的任务分为长任务和短任务。规定持续时间超过 50ms 的任务为长任务,低于 50ms 的任务为短任务。长任务中超过 50ms 的时间被认为是“阻塞”的,因此,TBT 是所有长任务中阻塞时间的总和。TBT = FCP 和 TTI 之间发生的每个长任务的「阻塞时间」总和。例:
上图,有三个长任务,两个短任务。
而 TBT 时长为 200+40+105=345ms。
累计位移偏移,CLS(Cumulative Layout Shift),记录了页面上非预期的位移波动。比如:页面渲染过程中突然插入一张巨大的图片或者说点击了某个按钮突然动态插入了一块内容等等相当影响用户体验的网站。这个指标就是为这种情况而生的,计算方式为:位移影响的面积 * 位移距离。
以上图为例,文本移动了 25% 的屏幕高度距离(位移距离),位移前后影响了 75% 的屏幕高度面积(位移影响的面积),那么 CLS 为 0.25 * 0.75 = 0.1875
。CLS 推荐值为低于 0.1,越低说明页面跳来跳去的情况就越少,用户体验越好。毕竟很少有人喜欢阅读或者交互过程中网页突然动态插入 DOM 的情况,比如说插入广告。
Vue 项目性能优化 — 实践指南(网上最全 / 详细)
[http://juejin.cn/post/6844903913410314247#heading-22]
gzip 是 GNUzip 的缩写,最早用于 UNIX 系统的文件压缩。HTTP 协议上的 gzip 编码是一种用来改进 web 应用程序性能的技术,web 服务器和客户端(浏览器)必须共同支持 gzip。目前主流的浏览器,Chrome,firefox,IE 等都支持该协议。常见的服务器如 Apache,Nginx,IIS 同样支持,gzip 压缩效率非常高,通常可以达到 70% 的压缩率。
HTTP2.0 新特性
[http://juejin.cn/post/6844903545532071943]
HTTP2.0 大幅度的提高了 web 性能,在 HTTP1.1 完全语义兼容的基础上,进一步减少了网络的延迟。实现低延迟高吞吐量。对于前端开发者而言,减少了优化工作。Http2 提供了以下一些新特性,对性能优化有一定帮助。
字体图标就是将图标制作成一个字体,使用时就跟字体一样,可以设置属性,例如 font-size、color 等,非常方便,并且字体图标是矢量图,不会失真。还有一个优点是生成的文件特别小,无论是加载还是打包所消耗的资源都相对较小一些。
WebP 相对于 PNG、JPG 有什么优势?[http://www.zhihu.com/question/27201061]
图片往往是一个 h5 页面的重要组成部分,然而图片占用的资源往往也是很大的,因此图片优化在性能优化中占据很重要的地位。下面来看几种优化图片的方式。
image-webpack-loader
进行图片压缩。懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。
在教师端项目中登录重定向部分,由于历史代码逻辑问题,无法使用 react router 中的跳转方式,所以选择了使用location.herf
进行跳转。虽然,功能上没有问题,但是由于页面在登录过程中频繁地重新加载,导致登录重定向的过程十分缓慢,极大影响了用户体验,所以考虑将登录重定向部分代码进行重构,避免使用location.herf
。
CSS 性能优化的几个技巧[http://juejin.cn/post/7077347573740077069#heading-1]
想要优化 CSS 的性能,我们首先需要了解 CSS 的渲染规则,CSS 选择器是从右向左进行匹配的。 CSS 中更多的选择器是不会匹配的,所以在考虑性能问题时,需要考虑的是如何在选择器不匹配时提升效率。从右向左匹配就是为了达成这一目的的,通过这一策略能够使得 CSS 选择器在不匹配的时候效率更高。这样想来,在匹配时多耗费一些性能也能够想的通了。
所谓的 Dom 离线化就是将要操作的元素从文档流中脱离,然后再恢复它。离线的 DOM 不属于当前 DOM 树中的任何一部分,这也就意味着我们对离线 DOM 处理就不会引起页面的回流与重绘。可以使用display: none
,上面我们说到了 (display: none
) 将元素从渲染树中完全移除,元素既不可见,也不是布局的组成部分,之后在该 DOM 上的操作不会触发回流与重绘,操作完之后再将display
属性改为显示,只会触发这一次回流与重绘。
【长文慎入】一文吃透 React SSR 服务端渲染和同构原理[http://juejin.cn/post/6844903943902855176]
在 SPA 模式下,所有的数据请求和 Dom 渲染都在浏览器端完成,所以当我们第一次访问页面的时候很可能会存在“白屏”等待,而服务端渲染所有数据请求和 html 内容已在服务端处理完成,浏览器收到的是完整的 html 内容,可以更快的看到渲染内容,在服务端完成数据请求肯定是要比在浏览器端效率要高的多。
SSR 对 SEO 是相对友好的,有些网站的流量来源主要还是靠搜索引擎,所以网站的 SEO 还是很重要的,而 SPA 模式对搜索引擎不够友好,要想彻底解决这个问题只能采用服务端直出。
当然,SSR 也会带了很多额外的工作量,而且会很大程度上增加项目的复杂度,这里需要做一个工作量与优化之间的权衡~
理解 JS 的节流、防抖及使用场景[http://juejin.cn/post/6844903669389885453]
防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout。防抖可以比作等电梯,只要有一个人进来,就需要再等一会儿。业务场景有避免登录按钮多次点击的重复提交。
节流:控制流量,单位时间内事件只能触发一次,与服务器端的限流 (Rate Limit) 类似。代码实现重在开锁关锁 timer=timeout; timer=null。节流可以比作过红绿灯,每等一个红灯时间就可以过一批。
浅谈 HTML5 Web Worker
[http://juejin.cn/post/6844903496550989837]
Web Worker 是 HTML5 标准的一部分,这一规范定义了一套 API,它允许一段 JavaScript 程序运行在主线程之外的另外一个线程中。可以加载一个 JS 进行大量的复杂计算而不挂起主进程,并通过 postMessage,onmessage 进行通信,解决了大量计算对 UI 渲染的阻塞问题。
图片资源是每个项目无法绕开的,在项目中,图片资源往往是占打包体积比例较大的,并且图片资源的压缩效率也不是特别理想,所以为减少项目最后的打包体积,可以将图片上传至 CDN ,通过动态加载的方式引入图片,这样就可以避免图片增加打包体积了。
SourceMap 的可选值如下(+ 号越多,代表速度越快,- 号越多,代表速度越慢, o 代表中等速度 )
开发环境推荐:cheap-module-eval-source-map
生产环境推荐:cheap-module-source-map
原因如下:
如果你使用的是 webpack v5 或更高版本,是开箱机带的功能,但是你的 webpack 是 v5 以下或者希望自定义配置,那么需要安装 terser-webpack-plugin
。如果使用 webpack v4,则必须安装 terser-webpack-plugin
v4 的版本。
我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component
,然后可以只引入需要的组件,以达到减小项目体积的目的,如 import lodash
-> import lodash/get
。还可以使用一些支持 Tree Shaking 的库,如 import lodash
-> import lodash/get
。
上述列出的只是有关于前端性能优化的冰山一角,比较适合对优化手段了解较少的同学用于知识储备,有兴趣的同学可以继续阅读其他性能优化相关的文章。
下面分享几篇作者阅读过的一些较全的文章,可以帮助你更深层次了解: