# 前端架构与性能优化那些事

# 前端的性能到底对业务数据有多大的影响

来个小故事

从前有个工程师,特别注重代码细节,有一天他发现系统中的一段代码写的性能很差,因此,他用汇编重写了整段代码,执行效率足足提升了三倍。但是最后,大家发现,用户反馈性能丝毫没有提高,因为他优化的那个进程名字叫“System Idle”。

所以你看,性能优化不能只着眼于局部的代码。这里,我要提出一个我的观点:一切没有 profiling 的性能都是耍流氓。凡是真正有价值的性能优化,必定是从端到端的业务场景建立体系来考虑的。

总结:性能体系的建立可以分成以下几部分:

1.现状评估和建立指标;

2.技术方案;

3.执行;

4.结果评估和监控。

57%的⽤用户更更在乎⽹网⻚页在 3 秒内是否完成加载。 52%的在线⽤用户认为⽹网⻚页打开速度影响到他们对⽹网站的忠实度。 每慢 1 秒造成⻚页⾯面 PV 降低 11%,⽤用户满意度也随之降低降低 16%。 近半数移动⽤用户因为在 10 秒内仍未打开⻚页⾯面从⽽而放弃。

# 性能优化学徒

几个核心是:压缩 ,合并,md5

使用 HTML CSS HIND 对 HTML 的数量进行控制,HTML 数量如果多的话渲染的会比较慢,对 HTML 的数量进行严格把控,不能滥用 HTML

使用多个 CDN 的资源,多个 CDN 的优势:一般大型网站 Cookie 会非常的长,Cookie 比较烦的一点是每次请求会带去,然后后台 response 一个新的 Cookie,那么这个 Cookie 可能就会带来带去的,那么这么大的东西每次请求带来带去的会比较头痛,然而静态资源不需要 Cookie,那么就会使用到 CDN;那么这就是 CDN;CDN 的功能不仅仅是多资源很快的定位做缓存,并且可以节省 Cookie。

GZIP 的开启一般是 Nginx 中设置----》gzip:on

# 缓存优先级--服务器缓存策略

为什么会有这么多缓存:浏览器发展,http 的版本形态状态的设置。

优点:减少相应的延迟。减少网络带宽消耗。本地缓存不可控。

一般库文件才会使用 http 缓存,库文件一般不会频繁变动,所有一般是强缓

业务文件是一般是 etag 和离线缓存

# 离线缓存--localstorage 的使用

https://github.com/addyosmani/basket.js (opens new window)

1.首先使用 webpack-manifest-plugin,打印出 md5.js

例如

{
  "a.js": "axx4.js",
  "omega.js": "mods/omega.0987654321.js"
}
1
2
3
4

2.本地缓存去取 a.js

3.有激活 js addScript

3-1 a.js -> axx2.js 对比

3-2 更新流程 a.js -> axx4.js

3-3 删除 axx2.js

3-4 跳到下一步

4.没有

4-1 请求 axx4.js

4-1 axx4.js 放到缓存

# from memory cache 与 from disk cache

1.浏览器 Network 的 Size 栏

在浏览器开发者工具的 Network 的 Size 栏会出现的三种情况:

from memory cache

from disk cache

资源本身大小(比如:13.6K)

2.三级缓存原理

1)、先查找内存,如果内存中存在,从内存中加载;

2)、如果内存中未查找到,选择硬盘获取,如果硬盘中有,从硬盘中加载;

3)、如果硬盘中未查找到,那就进行网络请求;

4)、加载到的资源缓存到硬盘和内存;

3.区别

根据系统的配置环境分配 from memory cache 或 from disk cache

4.几种状态的执行顺序

现加载一种资源(例如:图片):

访问-> 200 -> 退出浏览器

再进来-> 200(from disk cache) -> 刷新 -> 200(from memory cache)

# http

http2 出现也就可以放弃打包压缩那一步了

# 渲染中性能优化

# 网页渲染流程

1-1.获取 dom 分割成多层 Parse HTML

1-2.对每个层计算样式结果 Recalculate Style

1-3 为每个节点生成图形和位置 重排 Layout

1-4 将每个节点绘制并填充到图层的位图中。重绘 Paint

1-5 绘制出来的纹理上传到 GPU Composite Layers

2 大致流程 Layout 、Paint 、Composite Layers

3 网页分层

根元素 position transform 半透明 滤镜 canvas video overflow

GPU 参与 参与好处:跨过 重排 重绘

CSS3d video webgl transform 滤镜

4.cpu gpu

相同点:两者总有总线和外界联系 ,有自己的缓存体系 以及数字和逻辑运算单元,为了完成计算任务而生的

不同点: cpu 主要负责操作系统和应用程序。而 gpu 负责和显示相关的 ,gpu 能干的活 cpu 都能干只不过效率低

5.有些属性读会造成重排

重绘不一定引起重排,重排一定会引起重绘。

会引起重排属性:offset scroll width height

建议 dom 读写分离 读:ele.height ele.offset

下一帧的时候再去设置相关的值 requestAnimationFrame requestIdleCallback(浏览器支持的不是很好)。60 帧 1000 毫秒内渲染出来

# ⻚页⾯面加载性能优化

FP(First Paint) 首次绘制

FCP (First Contentful Paint), ⾸次 有内容的绘制

FMP (First Meaningful Pain) ⾸ 次有意义的绘制 没有绝对,自己决定

TTI (Time To Interactive), 可交互 时间 整个页面 ok

<div class="container">
    <div class="ball" id="ball">ball</div>
</div>

const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        console.log(entry);
    }
});

observer.observe({ entryTypes: ['paint'] })
1
2
3
4
5
6
7
8
9
10
11

PerformancePaintTiming {name: “first-paint”, entryType: “paint”, startTime: 16.30499999737367, duration: 0}

duration: 0

entryType: “paint”

FP

name: “first-paint”

startTime: 16.30499999737367

proto: PerformancePaintTiming

index.html:61

FCP

PerformancePaintTiming {name: “first-contentful-paint”, entryType: “paint”, startTime: 16.315000000759028, duration: 0}

duration: 0

entryType: “paint”

name: “first-contentful-paint”

startTime: 16.315000000759028

proto: PerformancePaintTiming

验证

let arr = [];
for (let i = 0; i < 10000000; i++) {
    arr.push(i)
}

const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        console.log(entry);
    }
});

observer.observe({ entryTypes: ['longtask'] })
1
2
3
4
5
6
7
8
9
10
11
12

PerformanceLongTaskTiming {attribution: Array(1), name: “self”, entryType: “longtask”, startTime: 12.879999994765967, duration: 303.82500000996515}

attribution: [TaskAttributionTiming]

duration: 303.82500000996515

longtask

entryType: “longtask”

name: “self”

startTime: 12.879999994765967

proto: PerformanceLongTaskTiming