1. 前端性能优化
性能优化原则:多使用内存、缓存等,减少CPU计算量,减少网络加载耗时。
1. 加载资源优化
对于页面加载慢的问题,一般是由于页面加载资源过多,并且资源过大导致。
-
解决页面加载资源过多,资源过大:
对于图片过多
- 通过懒加载的方式处理非首屏的图片,懒加载原理就是先不将图片的真实地址赋值src,而是使用一个属性比如data-src,暂存,然后监听滚动条事件,当滚动条距离浏览器顶部的高度满足一定条件时,就将 data-src 的值赋值到 src 上。
- 对于小图标可以采用 iconfont 的方式解决。设置font-family的css属性。
- 对于小图片可以采用雪碧图的方式解决。把所有小图片拼接到一张大图片上,使用雪碧图可以减少网络请求的次数,加快响应速度,通过background-position,去定位图片在屏幕的哪个位置
- 小图使用 base64 格式
对于其他资源过多
- 通过 nginx 服务器来做资源文件的合并或者通过 Webpack 等打包工具进行物理打包
- 对于需要引入一些大型第三方库的时候,可以通过按需加载的方式
- 可以通过前端路由懒加载的方式进行动态路由的加载
解决资源过大
可以通过 Webpack 来进行代码和图片的压缩 -
减少访问次数:可以使用缓存,如果存放在本地缓存中的资源还可以使用时,直接从缓存中获取。
-
使用更快的网络:CDN
CDN的全称是Content Delivery Network,即内容分发网络。其目的是通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络”边缘”,使用户可以就近取得所需的内容,解决Internet网络拥塞状况,提高用户访问网站的响应速度。从技术上全面解决由于网络带宽小、用户访问量大、网点分布不均等原因,解决用户访问网站的响应速度慢的根本原因
2. 渲染优化
- 首先渲染的前提是生成渲染树,所以 HTML 和 CSS 肯定会阻塞渲染。因此一般将 script 标签放在 body 标签底部或者给 script 标签添加 defer 或者 async 属性。
- 优化重排重绘导致的浏览器卡顿
- 浏览器自己的优化:浏览器会维护1个队列,把所有会引起重排、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让多次的重排、重绘变成一次重排重绘。
- 合并多次元素样式的修改,减少对渲染树的操作次数。
- 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流
- 将需要多次重排的元素,position属性设为absolute或fixed,元素脱离了文档流,它的变化不会影响到其他元素;
- 操作 DOM 可能还会带来重排重绘的情况,导致浏览器卡顿
优化DOM操作的性能的方法有:
(1)、对DOM查询进行缓存,不把节点的属性值放在一个循环里当成循环里的变量
例:(2)、将频繁的操作改为一次性操作,可以使用 document.createDocumentFragment 创建虚拟节点,把频繁的DOM操作一次性完成。
例:
(3)、vue框架使用虚拟 DOM,本质上就是用 JS 数据来模拟真实 DOM树,生成虚拟DOM,使用diff算法比较新旧两棵虚拟DOM树,将变化的地方记录下来,使用patch算法将改变的地方一次性渲染到真实DOM树上,从而大大减少了操作真实
DOM 的次数。
2. 为什么操作 DOM 慢
因为 DOM 是属于渲染引擎中的东西,而 JS 又是 JS 引擎中的东西。当我们通过 JS 操作 DOM 的时候,其实这个操作涉及到了两个线程之间的通信,所以存在一些性能上的损耗。操作 DOM 次数一多,也就等同于一直在进行线程之间的通信,并且操作 DOM 可能还会带来重排重绘的情况,所以也就导致了性能上的问题。
经典面试题:插入几万个 DOM,如何实现页面不卡顿(超长列表的渲染)?
对于这道题目来说,首先我们肯定不能一次性把几万个 DOM 全部插入,这样肯定会造成卡顿,所以解决问题的重点应该是如何分批次部分渲染 DOM。
虚拟滚动(virtualized scroller)技术
这种技术的原理就是只渲染可视区域内的内容,非可见区域完全不渲染,当滚动发生时,实时去替换渲染的内容,通过计算动态获得可视区域内的列表项,并将非可视区域内存在的列表项删除。
1.计算当前可视区域起始数据索引(startIndex)
2.计算当前可视区域结束数据索引(endIndex)
3.计算当前可视区域的数据,并渲染到页面中
4.计算startIndex对应的数据在整个列表中的偏移位置startOffset并设置到列表上