【慕课】前端性能优化企业级解决方案(中)

271 阅读7分钟

最近重新整理 慕课(前端性能优化企业级解决方案 6大角度+大厂视野)。

所以打算从 0 - 1 记录下来如何使用性能优化工具、如何分析前端性能优化,以及主流的前端性能优化方案。

全程采用案例分析的方式,一步一步敲开前端性能分析和优化的大门。

这是 前端性能优化企业级解决方案 的第二篇 渲染优化、代码优化、资源优化

渲染优化

现代浏览器渲染原理-关键渲染路径

什么是关键渲染路径(critical rendering path)?

描述了渲染从触发绘制的整个过程。

image.png

  1. JavaScript

触发我们的视觉变化(JS、CSS 等方式)。

  1. Style

浏览器重新对样式进行计算。

  1. Layout

布局。

  1. Paint

真正开始 绘制页面。文字、颜色、图片、阴影等。

  1. Composite

复合。

如何查看浏览器的渲染流程?

Performance 分析渲染过程。

image.png

浏览器拿到服务器的资源,都做了什么?

浏览器通过解释器把文本翻译能理解的数据结构。

  1. html 是怎么被转换的?

构建DOM对象。html -> DOM tree

image.png

  1. css 是怎么被转换的?

构建CSSDOM对象。 css -> CSS tree

image.png

  1. 浏览器构建渲染树

DOM + CSSDOM => Render Tree

合并把真正需要显示的内容留下,不需要显示的内容去掉,浏览器知道渲染的具体内容位置

image.png

布局(layout)和绘制(paint)

layout(回流)

布局计算每个节点精确的位置大小 - 盒模型。

  • 触发layout 的操作ss
添加/删除 元素
操作styles
display:none
offsetLeft,scrollTop,clientWidth
移动元素位置
修改浏览器大小、字体大小

避免layout thrashing 布局抖动

避免回流,读写分离。

  • 使用FastDOM

wilsonpage/fastdom: Eliminates layout thrashing by batching DOM measurement and mutation tasks (github.com)

paint(绘制)

绘制是像素化每个节点的过程。

  • 注意

GPU加速的动画,直接走Composite(不会经过layout、paint) 的过程。

复合线程(compositor thread)与图层(layers)

  1. 复合线程做了什么?

页面拆分图层进行绘制,再进行复合

  • 默认情况

默认情况下是由浏览器来决定的,分析元素与元素之间是否有相互的影响。

如果某些元素对其他元素造成的影响非常的多,就会被提取成一个单独的图层。

  • 主动提取

把一些元素主动提取成一个图层。

.card {
    whil-change: 'transform';    // transform、opaicty
}
  1. 利用DevTools 了解网页的图层拆分情况

image.png

  1. 哪些样式仅影响复合

极大的提高关键渲染路径的效率。

image.png

对案例图层,进行性能分析。

开发者工具 -》 Performance -》 录制 -》 触发 动画 -》 关闭录制

image.png

transform、opacity 等样式,仅仅影响复合,不会触发layout(回流)和paint(重绘)

高频事件防抖

  1. 一帧的生命周期

事件 -> JS -> 一帧开始 -> rAF -> layout -> Paint

image.png

rAF 浏览器调度的,尽量的在每一次绘制之前触发rAF。以满足能达到60FPS 这个效果。

案例:---

React时间调度实现

requestIdleCallback 的兼容性问题,react 通过 rAF模拟实现了rIC。

代码优化

快来看看怎样写出真正高性能的代码。

JS开销和如何缩短解析时间

JS 的开销在哪里?

解析、编译的时间太长。

加载 -》 解析&编译(2s) -》执行(1.5s)

image.png

解决方案:

  1. Code splitting 代码拆分,按需加载

  2. Tree shaking 代码减重

  3. 避免长任务

  4. 避免超过1KB的行间脚本

  5. 只用rAF 和 rIC 进行时间调度

  6. 渐进式启动

可见不可交互 VS 最小可交互资源集。

先加载首屏,剩下资源延时加载

配合V8有效优化代码

V8 编译原理?

V8 引擎拿到JS源代码 -》 解析 -》 AST -》 解释器 -》优化 -》字节码 -》 机器码。 image.png

编译过程会进行优化。

运行时可能发生发优化

V8优化机制:

  1. 脚本流

当下载的脚本大于30kb 的时候,会单独开一个线程,对着30KB的内容先进行解析。

当整个脚本都加载完成之后,再进行解析的时候,效率就提高了,因为前面的30KB已经解析了。

把所有解析的内容进行合并,就可以进行执行了。

  1. 字节码缓存 s

重复使用的片段,缓存起来。

  1. 懒解析

是对于函数而言的。

先不去解析函数内容,等真正要用的时候再去解析

函数优化

函数的解析方式。

  1. 懒解析

先不去解析函数内容,等真正要用的时候再去解析。

  1. 饥饿解析

声明的时候就去解析。

语法: 函数声明包上 ()

const add = ((a, b) => a + b)

对象优化

对象优化可以做哪些?

  1. 相同顺序初始化对象成员,避免隐藏类型的调整

编译器在解析的时候,会根据自己的推断给这些变量赋予 隐藏类型(21种)。

image.png

  1. 实例化后避免添加新属性

image.png

  1. 尽量使用Array 代替 array-like 对象

image.png

  1. 避免读取超过数组的长度

image.png

  1. 避免元素类型转换

image.png

HTML优化

  1. 减少iframes 使用

  2. 压缩空白符

  3. 避免节点深层级嵌套

  4. 避免table布局

  5. 删除注释

  6. CSS& JavaScript 尽量外链

  7. 删除元素默认属性

CSS对性能的影响

利用DevTools测量样式计算开销?

image.png

优化:

  1. 降低CSS对渲染的阻塞。

  2. 利用GPU进行完成动画。

  3. 使用contain 属性。

image.png

  1. contain: layout

盒子里的子元素和盒子外的子元素,没有任何的关系(里面怎么变化不会影响外面,外面怎么变化也不会影响盒子里面)。

  1. 使用 font-display属性。

文字更早的显示在页面,解决文字闪动的问题。

资源优化

资源的压缩与合并

为什么要压缩、合并?

见效最明显的优化方法。

减少http请求数量。

减少请求资源的大小。

  1. html 的压缩

html-minifier

  1. CSS 的压缩

clean-css 等npm 工具。

  1. JS 压缩与混淆

Webpack 对JS在构建时压缩。

  1. CSS JS文件合并

图片格式优化

图片优化的方案?

image.png

  1. 选择正确的图片格式

  2. 合适的图片大小

  3. 适配不同屏幕的尺寸

  4. 压缩

  5. 加载优先级

  6. 懒加载

  7. 利用工具

图片格式比较

  1. JPEG/JPG
  • JPEG/JPG 的优点

有损压缩,压缩比高,色彩好。

  • 使用场景

大图。

  • 缺点

图片的纹理、边缘会有锯齿感和模糊。

  1. PNG
  • 优点

透明图。

  • 使用场景

小图,图标、logo。

  • 缺点

体积大

  1. WEBP
  • 优点

跟PNG达到相同的质量,体积更小

  • 缺点

浏览器兼容性。

图片加载优化

图片的懒加载

  1. 原生的图片懒加载方案

img 标签上添加 loading=lazy

需要浏览器支持,自定义和可扩展不太好。

  1. 第三方图片懒加载方案

verlok/lazyload

yall.js

Blazy

渐进式图片

  1. Baseline JPEG

基线格式的JPEG,行扫描的方式显示图片。

  1. Progressive JPEG

渐进式格式的JPEG,从模糊到清晰的显示图片。

image.png

渐进式图片的优缺点?

始终可以让用户看到图的全貌,慢慢从模糊到清晰的过程。

image.png

渐进式图片的解决方案?

  1. progressive-imgage

  2. ImageMagick

  3. libjpeg

  4. jpegtran

  5. jpeg-recompress

  6. imagemin

响应式图片

适配不同的屏幕尺寸,下载对应的图片资源。

  • 响应式加载

Srcset、Sizes 属性的使用。

  • picture 元素

字体优化

什么是FOIT和FOUT?

字体未下载完成时,浏览器隐藏或自动降级,导致字体闪烁

  • Flash Of Invisible Text

文字从看不到到看到

  • Flash Of Unstyled Text

文字从没有样式到看到样式

font-display

font-display: xxx 控制字体加载的行为。

支持以下属性值,表现方式如下:

INVISIBLE 不可见。

FALLBACK 默认字体。

WEBFONT 网站字体。

image.png

AJAX + Base64

解决兼容性问题?

使用Base64 将字体编码,保存到css / js 中。

  • 缺点

缓存问题:缓存依赖于css/js ,缓存不可控。