# 代码优化
# 解决方案
Code splitting 代码拆分,按需加载
Tree shaking 代码减重
# 减少主线程工作量
避免长任务
避免超过1kb的行间脚本
使用rAF和rIC进行时间调度
# v8优化
# 原理
源码 => 抽象语法树 => 字节码 Bytecode => 机器码
编译过程会进行优化
运行时可能发生反优化
# 优化机制
脚本流
字节码缓存
懒解析
# 函数优化
# 函数的解析方式
懒解析:只解析出外部函数需要的内容,而全量解析在调用这个函数时才发生
lazy parsing 懒解析 vs eager parsing 饥饿解析
利用Optimize.js 优化初次加载时间
export default () => {
const add = (a, b) => a*b; // lazy parsing
// const add = ((a, b) => a*b); // eager parsing
const num1 = 1;
const num2 = 2;
add(num1, num2);
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 对象优化
# 对象优化可以做哪些
以相同顺序初始化对象成员,避免隐藏类的调整。
实例化后避免添加新属性
尽量使用Array代替array-like 对象
# 例子1
class RectArea { // HC0
constructor(l, w) {
this.l = l; // HC1
this.w = w; // HC2
}
}
const rect1 = new RectArea(3,4); // 创建了隐藏类HC0, HC1, HC2
const rect2 = new RectArea(5,6); // 相同的对象结构,可复用之前的所有隐藏类
const car1 = {color: 'red'}; // HC0
car1.seats = 4; // HC1
const car2 = {seats: 2}; // 没有可复用的隐藏类,创建HC2
car2.color = 'blue'; // 没有可复用的隐藏类,创建HC3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 例子2
const car1 = {color: 'red'}; // In-object 属性
car1.seats = 4; // Normal/Fast 属性,存储在property store里,需要通过描述数组间接查找
1
2
2
# 例子3
Array.prototype.forEach.call(arrObj, (value, index) => { // 不如在真实数组上效率高
console.log(`${ index }: ${ value }`);
});
const arr = Array.prototype.slice.call(arrObj, 0); // 转换的代价比影响优化小
arr.forEach((value, index) => {
console.log(`${ index }: ${ value }`);
});
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 例子4
function foo(array) {
for (let i = 0; i <= array.length; i++) { // 越界比较
if(array[i] > 1000) { // 1.沿原型链的查找 2.造成undefined与数进行比较
console.log(array[i]); // 业务上无效、出错
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 例子5
const array = [3, 2, 1]; // PACKED_SMI_ELEMENTS
array.push(4.4); // PACKED_DOUBLE_ELEMENTS
1
2
3
2
3
# HTML优化
减少iframes使用
压缩空白符
避免节点深层级嵌套
避免使用table布局
删除注释
CSS&Javascript尽量外链
删除元素默认属性
# 必须使用iframes
延迟加载:等页面加载完后再修改iframes的地址进行加载
# 借助工具
- html-minifier
# CSS优化
降低CSS对渲染的阻塞
利用GPU进行完成动画
使用contain属性
使用font-display属性