leslie1943/blog

性能优化: 前端性能优化 24 条建议(下)

Opened this issue · 0 comments

前端性能优化 24 条建议(下)

🍊 13: 注意程序的局部性

一个编写良好的计算机程序常常具有良好的局部性, 它们倾向于引用最近引用过的数据项附近的数据项, 或者最近引用过的数据项本身, 这种倾向性, 被称为局部性原理.有良好局部性的程序比局部性差的程序运行得更快.

  • 时间局部性: 在一个具有良好时间局部性的程序中, 被引用过一次的内存位置很可能在不远的将来被多次引用.
  • 空间局部性: 在一个具有良好空间局部性的程序中, 如果一个内存位置被引用了一次, 那么程序很可能在不远的将来引用附近的一个内存位置

🍊 14: if-else 对比 switch

当条件值大于两个的时候, 使用 switch 更好.不过 if-else 也有 switch 无法做到的事情, 例如有多个判断条件的情况下, 无法使用 switch

🍊 15: 查找表

当条件语句特别多时, 使用 switchif-else 不是最佳的选择, 这时不妨试一下查找表.查找表可以使用数组和对象来构建:

const results = [result0,result1,result2,result3,result4,result5,result6,result7,result8,result9,result10,result11]
return result[index]

// 或者
const resultMap = {
    'red': result0,
    'green': result1,
    ...
    'black': resultN
}

🍊 16: 避免页面卡顿

60fps 与设备刷新率

目前大多数设备的屏幕刷新率为 60 次/秒.因此, 如果在页面中有一个动画或渐变效果, 或者用户正在滚动页面, 那么浏览器渲染动画或页面的每一帧的速率也需要跟设备屏幕的刷新率保持一致.

其中每个帧的预算时间仅比 16 毫秒多一点 (1 秒/ 60 = 16.66 毫秒).但实际上, 浏览器有整理工作要做, 因此您的所有工作需要在 10 毫秒内完成.如果无法符合此预算, 帧率将下降, 并且内容会在屏幕上抖动. 此现象通常称为卡顿, 会对用户体验产生负面影响.

假如你用 JavaScript 修改了 DOM, 并触发样式修改, 经历重排重绘最后画到屏幕上.如果这其中任意一项的执行时间过长, 都会导致渲染这一帧的时间过长, 平均帧率就会下降.假设这一帧花了 50 ms, 那么此时的帧率为 1s / 50ms = 20fps, 页面看起来就像卡顿了一样

// 对于一些长时间运行的 JavaScript,我们可以使用定时器进行切分,延迟执行. 
for(let i = 0; i < arr.length; i++){
    process(arr[i])
}

🍊 17: 使用 requestAnimationFrame 来实现视觉变化

从第 16 点我们可以知道,大多数设备屏幕刷新率为 60 次/秒,也就是说每一帧的平均时间为 16.66 毫秒. 在使用 JavaScript 实现动画效果的时候,最好的情况就是每次代码都是在帧的开头开始执行. 而保证 JavaScript 在帧开始时运行的唯一方式是使用 requestAnimationFrame

🍊 18: 使用 Web Workers

Web Worker 使用其他工作线程从而独立于主线程之外,它可以执行任务而不干扰用户界面. 一个 worker 可以将消息发送到创建它的 JavaScript 代码, 通过将消息发送到该代码指定的事件处理程序(反之亦然).
Web Worker 适用于那些处理纯数据,或者与浏览器 UI 无关的长时间运行脚本

🍊 19: 使用位操作

// 取模
if (value % 2) {
	// 奇数
} else {
	// 偶数 
}
// 位操作
if (value & 1) {
	// 奇数
} else {
	// 偶数
}

// 取反
~~10.12 // 10
~~10 // 10
~~'1.5' // 1
~~undefined // 0
~~null // 0

// 位掩码
const a = 1
const b = 2
const c = 4
const options = a | b | c

// 选项 b 是否在options中
if(b & options){

}

🍊 20: 不要覆盖原生方法

无论你的 JavaScript 代码如何优化,都比不上原生方法. 因为原生方法是用低级语言写的(C/C++),并且被编译成机器码,成为浏览器的一部分. 当原生方法可用时,尽量使用它们,特别是数学运算和 DOM 操作.

🍊 21: 降低 CSS 选择器的复杂性

  • (1)浏览器读取选择器, 遵循的原则是从选择器的右边到左边取
#block .text p{
    color: red
}
/* 
    1: 查找所有的p元素
    2: 查找结果1中的元素是否有类名为text的父元素
    3: 查找结果2中的元素是否有id为block的父元素
 */
  • (2)CSS 选择器优先级
内联 > id选择器 > 类选择器 > 标签选择器
  • 根据以上两个信息得出:
# 1: 选择器越短越好
# 2: 尽量使用高优先级的选择器,例如 ID 和类选择器
# 3: 避免使用通配符

🍊 22: 使用 flexbox 而不是较早的布局模型

性能好

🍊 23: 使用 transform 和 opacity 属性更改来实现动画

CSS中, transformopacity这2个属性不会触发重排和重绘, 它们是由合成器(composite)单独处理的属性

🍊 24: 合理使用规则,避免过度优化

性能优化分为两类:

  • 加载时优化

  • 运行时优化
    上述 23 条建议中,属于加载时优化的是前面 10 条建议,属于运行时优化的是后面 13 条建议。通常来说,没有必要 23 条性能优化规则都用上,根据网站用户群体来做针对性的调整是最好的,节省精力,节省时间

  • 检查加载性能: 一个网站的加载性能如何主要看白屏时间(输入网址,到网页开始显示内容的时间)首屏时间(输入网址,到页面完全渲染的时间), 将一下脚本放在<head></head>中就能获取白屏时间

new Date() - performance.timing.navigationStart

检查运行性能: