前端性能优化总结

6次阅读

共计 1120 个字符,预计需要花费 3 分钟才能阅读完成。

记录性能优化相关的知识。

Chrome DevTools — Network

DOMContentLoaded: DOM 树构建完成的时间
Load: 页面加载完毕。即 DOM 树构建完成后,加载完图片等外部资源的时间
Finish: 是页面上所有 HTTP 请求发送到响应完成的时间

Waterfall

根据 HTTP 请求的不同阶段来进行排序

Start Time:请求开始的时间
Response Time: 资源开始下载的时间
End Time: 请求结束的时间
Total Duration: 请求整个完整过程的时间
Latency 请求等待响应的时间

如下图所示,Waterfall 右键之后选择 Total Duration,则请求按照整个持续时间排序,不同的颜色代表不同的资源文件,浅色的部分代表资源的等待时间,深色的部分代表下载时间。

懒加载

一、为什么要用懒加载?

二、懒加载的实现原理

  1. 首先,将图片的地址放在其它属性 (data-url) 中,而不是 src。
  2. 页面加载时根据 scrollTop 的值判断图片是否在可视区域, 如果在可视区域,则将 data-url 属性中的值取出存放到 src 属性中(首屏的图片可以直接加载)。
  3. 在滚动过程中,判断图片是否在可视区域,如果在,则将 data-url 属性中的值放到 src 属性中。

图片优化

图片优化的几种方式:

CSS Sprite 和 BASE64 的对比

各个类型图片的对比

延迟加载第三方 JS

  • defer 属性:渲染 DOM 的过程将和 JS 脚本加载的过程异步进行,但是 JS 脚本的执行要在所有元素解析完成之后(只适用于外部脚本文件)
  • async 属性:加载和渲染 DOM 的过程将和 JS 脚本的加载与执行的过程异步进行(只适用于外部脚本文件)
  • defer 按照加载顺序执行脚本文件,async 则不会按照声明顺序执行

具体区别见下图:

绿色线代表 HTML 解析;蓝色线代表 JS 脚本读取时间;红色线代表 JS 脚本执行时间。

Preload 和 Prefetch

preload 提供了一种声明式的命令,让浏览器提前加载指定资源 (加载后并不执行),在需要执行的时
候再执行。

  • 将加载和执行分离开,不阻塞渲染和 document 的 onload 事件
  • 提前加载指定资源

使用:

prefetch: 告诉浏览器未来可能会使用到的某个资源,浏览器就会在闲时去加载对应的资源。

使用:

Gzip -> Brotil

Brotli 压缩算法具有多个特点,最典型的是以下 3 个:

  • 针对常见的 Web 资源内容,Brotli 的性能相比 Gzip 提高了 17-25%;
  • 当 Brotli 压缩级别为 1 时,压缩率比 Gzip 压缩等级为 9(最高)时还要高;
  • 在处理不同 HTML 文档时,Brotli 依然能够提供非常高的压缩率。

参考文档:

https://segmentfault.com/a/11…

正文完
 0

前端性能优化总结

6次阅读

共计 2253 个字符,预计需要花费 6 分钟才能阅读完成。

1. 原则
多使用内存,缓存或者其他方法
减少 CPU 计算,减少网络请求
减少 IO 操作(硬盘读写)
2. 加载资源优化
静态资源的合并和压缩。
静态资源缓存(浏览器缓存策略)。
使用 CDN 让静态资源加载更快。
3. 渲染优化
CSS 放 head 中,JS 放 body 后
图片懒加载
减少 DOM 操作,对 DOM 操作做缓存
减少 DOM 操作,多个操作尽量合并在一起执行
事件节流
尽早执行操作 DOMContentLoaded
4. 示例
4.1 资源合并
a.js b.js c.js — abc.js
4.2 缓存
通过连接名称控制缓存
<script src=”abc_1.js” ></script>
只有改变内容的时候,链接名称才会改变。
4.3 懒加载
<img src=”preview.png” realsrc=”abc.png” id=”img1″ />
<script>
var i = document.getElementById(‘img1’);
i.src = i.getAttribute(‘realsrc’);
</script>
4.4 缓存 dom 查询
// 没有缓存 dom
for (let i = 0; i < document.getElementsByTagName(‘p’).length; i++) {

}

// 缓存 dom
var p = document.getElementsByTagName(‘p’);
for (let i = 0; i < p.length; i++) {

}
4.5 合并 dom 插入
var listNode = document.getElementById(‘list’);
var flag = document.createDocumentFragment();
var li;
for (let i = 0; i < 10; i++) {
li = document.createElement(‘li’);
li.innerHTML = i;
flag.appendChild(li);
}
listNode.appendChild(flag);
10 次 dom 插入 —> 1 次 dom 插入
4.6 事件节流
监听文字改变事件,无操作 100 毫秒后执行操作,不用每次触发。
var textarea = document.getElementById(‘ta’);
var timeoutId;
textarea.addEventListener(‘keyup’,function(){
if(i){
clearTimeout(i);
}
timeoutId = setTimeout(() => {
// 操作
}, 100);
});
事件节流主要用于触发频率较高的事件,设定一个缓冲触发事件。
补充
异步加载
非核心代码异步加载 — 异步加载的方式 — 区别
1. 动态脚本加载
用 js 创建
2.defer
3.async
<script src=”script.js”></script>
没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script async src=”script.js”></script>
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
<script defer src=”myscript.js”></script>
有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。
关于 defer,我们还要记住的是它是按照加载顺序执行脚本的
标记为 async 的脚本并不保证按照指定它们的先后顺序执行。对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行。
浏览器缓存
总结的非常好
浏览器缓存 — 缓存的分类 — 缓存的原理
缓存就是 html 文件在本地存在的副本,
强缓存
发现有缓存直接用。
Expires: 绝对时间,判断客户端日期是否超过这个时间
Cache-Control:相对时间,判断访问间隔是否大于 3600 秒

// 在设定时间之前不会和服务端进行通信了
// 如果两个都下发以后者为准
协商缓存
询问服务器缓存是否可以用,在进行判断是否用。
Last-Modified/If-Modified-Since
第一次请求,respone 的 header 加上 Last-Modified(最后修改时间)

再次请求,在 request 的 header 上加上 If-Modified-Since

和服务端的最后修改时间对比,如果没有变化则返回 304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。

浏览器收到 304 的响应后,就会从缓存中加载资源

如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified 的 Header 在重新加载的时候会被更新

Etag/If-None-Match
这两个值是由服务器生成的每个资源的唯一标识字符串,只要资源有变化就这个值就会改变;其判断过程与 Last-Modified/If-Modified-Since 类似,他可以精确到秒的更高级别。
DNS 预解析
<meta http-equiv=”x-dns-prefetch-control” content=”on”>
<link rel=”dns-prefetch” href=”//www.zhix.net”>
在一些浏览器的 a 标签是默认打开 dns 预解析的,在 https 协议下 dns 预解析是关闭的,加入 mate 后会打开。

正文完
 0