前端性能优化
CDN
CDN 是什么东西,它又有什么作用呢,对于每一个前端开发来说页面的响应速度是个令人头疼的问题,我们都知道浏览器具有缓存,但是这只是解决页面被再次访问的速度,对于我们需要首次提升访问速度,通常我们就需要采用 CDN 进行加速了。
工作原理
通过流程图我们可以发现 CDN 的原理就是将网站中的静态资源放到 CDN 服务器中,然后 CDN 服务器在进行负载均衡到每个地区的服务器中,当不同地区的用户访问网站的时候,CDN 就会通过就近原则将资源从最近的服务器里请求过来,从而缩短用户的请求时间,从而来提高用户的体验。
懒加载
当我们网页中有许多图片时,这样就会影响用户的体验,这时候我们就可以通过图片懒加载的方式,等到用户快要访问到图片时,在加载图片,这样就优化了用户的体验。
虚拟列表
我们需要展示大量数据表格数据时,后端没有分页这个时候我们就需要用到虚拟列表了。
回流与重绘
1、回流
当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染部分或者全部文档的过程就称为回流。
导致回流的原因:
- 页面的首次渲染
- 浏览器的窗口大小发生变化
- 元素的内容发生变化
- 元素的尺寸或者位置发生变化
- 元素的字体大小发生变化
- 激活 CSS 伪类
- 查询某些属性或者调用某些方法
- 添加或者删除可见的 DOM 元素
2、重绘
当页面中某些元素的样式发生变化,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这个过程就是重绘。
导致重绘的原因:
- color、background 相关属性:background-color、background-image 等
- outline 相关属性:outline-color、outline-width 、text-decoration
- border-radius、visibility、box-shadow
注意: 当触发回流时,一定会触发重绘,但是重绘不一定会引发回流。
3、如何避免回流与重绘?
减少回流与重绘的措施:
- 操作 DOM 时,尽量在低层级的 DOM 节点进行操作
- 不要使用
table
布局, 一个小的改动可能会使整个table
进行重新布局 - 使用 CSS 的表达式
- 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式。
- 使用 absolute 或者 fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素
- 避免频繁操作 DOM,可以创建一个文档片段
documentFragment
,在它上面应用所有 DOM 操作,最后再把它添加到文档中 - 将元素先设置
display: none
,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。 - 将 DOM 的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于浏览器的渲染队列机制。
浏览器针对页面的回流与重绘,进行了自身的优化——渲染队列
浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批处理。这样就会让多次的回流、重绘变成一次回流重绘。
上面,将多个读操作(或者写操作)放在一起,就会等所有的读操作进入队列之后执行,这样,原本应该是触发多次回流,变成了只触发一次回流。
防抖和节流
防抖
在单位时间内,用户触发了操作,则重新计时。
使用场景:
- 输入框搜索
- resize 窗口
function debounce(fn, time) {
let timer = null;
return function () {
const context = this;
const args = [...arguments];
timer && clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(context, args);
}, time);
}
}
节流
在单位时间内,用户触发了操作,只会等到时间到了在执行。
使用场景:
- 鼠标不断点击触发,mousedown(单位时间内只触发一次)
- 监听滚动事件
// 计时器版本
function throttle(fn, time) {
let timer = null;
return function () {
const context = this;
const args = [...arguments];
!timer && timer = setTimeout(() => {
fn.apply(context, args);
timer = null;
}, time);
}
}
// 时间戳版本
function throttle(fn, time) {
let preTime = Date.now();
return function () {
const context = this;
const args = [...arguments];
const curTime = Date.now();
if (curTime - preTime >= time) {
setTimeout(() => {
fn.apply(context, args);
preTime = curTime;
}, time);
}
}
}
图片优化
-
可以使用 CSS 实现的尽量用 CSS 实现。
-
使用雪碧图,减少对图片的请求
Webpack 优化
gzip 压缩、html 压缩、css 压缩、js 压缩、分包(减少单个 js 文件的体积、从而优化页面白屏)