前端性能优化

1. 懒加载

懒加载也叫做延迟加载按需加载,指的是在长网页中延迟加载图片数据,是一种较好的网页性能优化的方式。
在比较长的网页或应用中,如果图片很多,所有的图片都被加载出来,而用户只能看到可视窗口
的那一部分图片数据,这样就浪费了性能。
如果使用图片的懒加载就可以解决以上问题。在滚动屏幕之前,可视化区域之外的图片不会进行加载,在滚动屏幕时才加载。这样使得网页的加载速度更快,减少了服务器的负载。
懒加载适用于图片较多,页面列表较长(长列表)的场景中

特点

  • 减少无用资源的加载:使用懒加载明显减少了服务器的压力和流量,同时也减小了浏览器的负担。
  • 提升用户体验: 如果同时加载较多图片,可能需要等待的时间较长,这样影响了用户体验,而使用懒加载就能大大的提高用户体验。
  • 防止加载过多图片而影响其他资源文件的加载 :会影响网站应用的正常使用。

实现原理

图片的加载是由 src 引起的,当对 src 赋值时,浏览器就会请求图片资源。
根据这个原理,我们使用 HTML5 的 data-xxx 属性来储存图片的路径,在需要加载图片的时候,将 data-xxx 中图片的路径赋值给src,这样就实现了图片的按需加载,即懒加载
注意:data-xxx 中的 xxx 可以自定义,这里我们使用 data-src 来定义。
懒加载的实现重点在于确定用户需要加载哪张图片,在浏览器中,可视区域内的资源就是用户需要的资源。所以当图片出现在可视区域时,获取图片的真实地址并赋值给图片即可。

使用简单js书写懒加载的实现

  1. 浏览器可视区高度
    window.innerHeight
  2. 浏览器滚动的过的距离
    document.body.scrollTop
    或者
    document.documentElement.scrollTop
  3. 元素顶部距离文档顶部的高度
    imgs.offsetTop imgs是将要显示的元素
    实现条件:img.offsetTop < window.innerHeight + document.body.scrollTop
    图示
    在这里插入图片描述在这里插入图片描述

代码

<style>
.imgs {
	width: 500px;
	background-color: #aaa;
	border: 1px solid #ddd;
	margin: 0 auto;
	padding: 10px;

}

img {
	width: 100%;
	height: 300px;
	margin: 5px 0;
}
</style>
<div class="imgs">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/1.webp">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/2.webp">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/3.webp">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/4.webp">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/5.webp">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/6.webp">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/7.webp">
	<img src="../CSS/资源包/img/loading.jpg" alt="" data-src="../CSS/资源包/img/8.webp">
</div>
<script type="text/javascript">
	function lozyLoad() {
		const imgs = document.querySelectorAll('img')
		console.log(imgs);
		let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
		let winHeight = window.innerHeight;
		console.log('--------', scrollTop, winHeight);
		for (var i = 0; i < imgs.length; i++) {
			console.log(i, imgs[i].offsetTop);
			if (imgs[i].offsetTop < scrollTop + winHeight) {
				imgs[i].src = imgs[i].getAttribute('data-src')
			}
		}
	}
	lozyLoad()
	window.addEventListener('scroll', function() {
		lozyLoad()
	});
</script>

方法有很多哦~ 此例举出最易明白的

2.回流与重绘

概念

回流
当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染部分或者全部文档的过程就称为回流。
重绘
当页面中某些元素的样式发生变化,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这个过程就是重绘。

触发条件

回流

  • 页面的首次渲染
  • 浏览器的窗口大小发生变化
  • 元素的内容发生变化
  • 元素的尺寸或者位置发生变化
  • 元素的字体大小发生变化
  • 激活 CSS 伪类
  • 查询某些属性或者调用某些方法
  • 添加或者删除可见的 DOM 元素

在触发回流(重排)的时候,由于浏览器渲染页面是基于流式布局的,所以当触发回流时,会导致周围的 DOM 元素重新排列,它的影响范围有两种:
全局范围:从根节点开始,对整个渲染树进行重新布局
局部范围:对渲染树的某部分或者一个渲染对象进行重新布局

重绘
下面这些操作会导致重绘:
color、background 相关属性:background-color、background-image等
outline 相 关 属 性 : outline-color 、 outline-width 、text-decoration、border-radius、visibility、box-shadow
注意: 当触发回流时,一定会触发重绘,但是重绘不一定会引发回流

避免方法

减少回流与重绘的措施:

  1. 操作 DOM 时,尽量在低层级的 DOM 节点进行操作
  2. 不要使用 table 布局, 一个小的改动可能会使整个 table 进行重新布局
  3. 使用 CSS 的表达式
  4. 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式。
  5. 使用 absolute 或者 fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素
  6. 避免频繁操作 DOM,可以创建一个文档片段 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中
  7. 将元素先设置 display: none,操作结束后再把它显示出来。因为在display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
  8. 将 DOM 的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于浏览器的渲染队列机制。
  9. 浏览器针对页面的回流与重绘,进行了自身的优化——渲染队列浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批处理。这样就会让多次的回流、重绘变成一次回流重绘。

上面,将多个读操作(或者写操作)放在一起,就会等所有的读操作进入队列之后执行,这样,原本应该是触发多次回流,变成了只触发一次回流。

优化动画

对于如何优化动画,我们知道,一般情况下,动画需要频繁的操作DOM,就就会导致页面的性能问题,我们可以将动画的 position 属性设置为 absolute 或者 fixed,将动画脱离文档流,这样他的回流就不会影响到页面了。

防抖和节流

概念

函数防抖 是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。
函数节流 是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。

应用场景

防抖
按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次
服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊事 件 的 最 后 ⼀ 次 ,还 有 搜 索 联 想 词 功 能 类 似 ⽣ 存 环 境 请 ⽤lodash.debounce

节流
拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动
缩放场景:监控浏览器 resize
动画场景:避免短时间内多次触发动画引起性能问题

函数

防抖函数

<button class="btn">按钮</button>
function debounce(fn, wait) {
	let timer = null;
	return function() {
		let context = this;
		args = [...arguments];
		if (timer) {
			clearTimeout(timer)
		}
		timer = setTimeout(() => {
			fn.apply(context, args)
		}, wait);
	}
}

function consoleFun() {
	console.log(123456);
}
const btn = document.querySelector('.btn')
//当点击按钮后 1秒 后输出 123456 ,持续点出,也只会在最后一次开始计时1s后输出
btn.addEventListener('click', debounce(consoleFun, 1000))

节流函数

  1. 时间戳
    在这里插入图片描述
<button class="btn">按钮</button>
function throttle(fn, delay) {
	let preTime = Date.now();
	return function() {
		let context = this;
		let nowTime = Date.now();
		let args = [...arguments];
		console.log(nowTime, preTime, nowTime - preTime);
		if (nowTime - preTime >= delay) {
			preTime = Date.now();
			return fn.apply(context, args)
		}
	}
}

function consoleFun() {
	console.log('输出', 123456);
}
const btn = document.querySelector('.btn')
btn.addEventListener('click', throttle(consoleFun, 1000));//时间超过设定值就能触发,毫秒
  1. 定时器
function throttle(fn, wait) {
	let timeout = null;
	return function() {
		let context = this;
		let args = [...arguments];
		if (!timeout) {
			timeout = setTimeout(() => {
				fn.apply(context, args)
				timeout = null
			}, wait);
		}
	}
}

function consoleFun() {
	console.log('输出', 123456);
}
const btn = document.querySelector('.btn')
btn.addEventListener('click', throttle(consoleFun, 500))

对图片进行优化

  1. 不用图片。很多时候会使用到很多修饰类图片,其实这类修饰图片完全可以用 CSS 去代替。
  2. 对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用 CDN 加载,可以计算出适配屏幕的宽度,然后去请求相应裁剪好的图片。
  3. 小图使用 base64 格式
  4. 将多个图标文件整合到一张图片中(雪碧图:加载出一个图片之后,使用哪个图标就直接定位位置)
  5. 选择正确的图片格式:对于能够显示 WebP 格式的浏览器尽量使用 WebP 格式。因为 WebP格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,缺点就是兼容性并不好小图使用 PNG,其实对于大部分图标这类图片,完全可以使用 SVG 代替照片使用 JPEG。

扩展

图片格式及使用场景:
(1)BMP,是无损的、既支持索引色也支持直接色的点阵图。这种图片格式几乎没有对数据进行压缩,所以 BMP 格式的图片通常是较大的文件。
(2)GIF 是无损的、采用索引色的点阵图。采用 LZW 压缩算法进行编码。文件小,是 GIF 格式的优点,同时,GIF 格式还具有支持动画以及透明的优点。但是 GIF 格式仅支持 8bit 的索引色,所以 GIF 格式适用于对色彩要求不高同时需要文件体积较小的场景。
(3)JPEG 是有损的、采用直接色的点阵图。JPEG 的图片的优点是采用了直接色,得益于更丰富的色彩,JPEG 非常适合用来存储照片,与 GIF 相比,JPEG 不适合用来存储企业 Logo、线框类的图。因为有损压缩会导致图片模糊,而直接色的选用,又会导致图片文件较 GIF更大。
(4)PNG-8 是无损的、使用索引色的点阵图。PNG 是一种比较新的图片格式,PNG-8 是非常好的 GIF 格式替代者,在可能的情况下,应该尽可能的使用 PNG-8 而不是 GIF,因为在相同的图片效果下,PNG-8具有更小的文件体积。除此之外,PNG-8 还支持透明度的调节,而 GIF并不支持。除非需要动画的支持,否则没有理由使用 GIF 而不是 PNG-8。
(5)PNG-24 是无损的、使用直接色的点阵图。PNG-24 的优点在于它压缩了图片的数据,使得同样效果的图片,PNG-24 格式的文件大小要比 BMP 小得多。当然,PNG24 的图片还是要比 JPEG、GIF、PNG-8大得多。
(6)SVG 是无损的矢量图。SVG 是矢量图意味着 SVG 图片由直线和曲线以及绘制它们的方法组成。当放大 SVG 图片时,看到的还是线和曲线,而不会出现像素点。这意味着 SVG 图片在放大时,不会失真,所以它非常适合用来绘制 Logo、Icon 等。
(7)WebP 是谷歌开发的一种新图片格式,WebP 是同时支持有损和无损压缩的、使用直接色的点阵图。从名字就可以看出来它是为 Web 而生的,什么叫为 Web 而生呢?就是说相同质量的图片,WebP 具有更小的文件体积。现在网站上充满了大量的图片,如果能够降低每一个图片的文件大小,那么将大大减少浏览器和服务器之间的数据传输量,进而降低访问延迟,提升访问体验。目前只有 Chrome 浏览器和 Opera浏览器支持 WebP 格式,兼容性不太好。

在无损压缩的情况下,相同质量的 WebP 图片,文件大小要比 PNG 小26%;
在有损压缩的情况下,具有相同图片精度的 WebP 图片,文件大小要比 JPEG 小 25%~34%;
WebP 图片格式支持图片透明度,一个无损压缩的 WebP 图片,如果要支持透明度只需要 22%的格外文件大小。

⽤webpack 来优化前端性能

⽤webpack 优化前端性能是指:优化 webpack 的输出结果,让打包的最终结果在浏览器运⾏快速⾼效。

  1. 压缩代码:删除多余的代码、注释、简化代码的写法等等⽅式。可以利⽤webpack的 UglifyJsPlugin 和 ParallelUglifyPlugin 来压缩JS⽂件, 利⽤ cssnano (css-loader?minimize)来压缩 css
  2. 利⽤CDN 加速: 在构建过程中,将引⽤的静态资源路径修改为 CDN 上对应的路径。可以利⽤webpack 对于 output 参数和各 loader 的publicPath 参数来修改资源路径
  3. Tree Shaking: 将代码中永远不会⾛到的⽚段删除掉。可以通过在启动 webpack 时追加参数 --optimize-minimize 来实现
  4. Code Splitting: 将代码按路由维度或者组件分块(chunk),这样做到按需加载,同时可以充分利⽤浏览器缓存
  5. 提取公共第三⽅库: SplitChunksPlugin 插件来进⾏公共模块抽取, 利⽤浏览器缓存可以⻓期缓存这些⽆需频繁变动的公共代码

提⾼webpack 的构建速度

  1. 多⼊⼝情况下,使⽤ CommonsChunkPlugin 来提取公共代码
  2. 通过 externals 配置来提取常⽤库
  3. 利⽤ DllPlugin 和 DllReferencePlugin 预编译资源模块 通过DllPlugin 来对那些我们引⽤但是绝对不会修改的 npm 包来进⾏预编译,再通过 DllReferencePlugin 将预编译的模块加载进来。
  4. 使⽤ Happypack 实现多线程加速编译
  5. 使⽤ webpack-uglify-parallel 来提升 uglifyPlugin 的压缩速度。原理上 webpack-uglify-parallel 采⽤了多核并⾏压缩来提升压缩速度
  6. 使⽤ Tree-shaking 和 Scope Hoisting 来剔除多余代码

内存泄漏

以下四种情况会造成内存的泄漏:
意外的全局变量:由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收。
被遗忘的计时器或回调函数:设置了 setInterval 定时器,而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收。
脱离 DOM 的引用:获取一个 DOM 元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以它也无法被回收。
闭包:不合理的使用闭包,从而导致某些变量一直被留在内存当中。

文章字多数手打,如有细节错误,请指出,谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值