新版本上线了,头发也快长出来了。老板说用户反映页面加载慢,让鹿鹿继续做性能优化,那么问题来了,怎么搞?摸摸刚长出来的头发,鹿鹿准备去请教下大姥。
性能优化
大姥:前端做性能优化嘛,主要是两个原则
。
- 多使用内存、缓存或者其他方法
- 减少CPU计算、减少网络请求
鹿鹿:看着很有道理的样子,那从哪入手
呢?
大姥: 用户在屏幕前面做啥呢,不就是耐心等着页面加载和对页面进行操作嘛,你减少些请求和加载,用户就可以少等会了。
- 加载页面和静态资源
- 页面渲染
鹿鹿:大姥就是大姥,秒懂!(眼前一亮)思来想去,列下清单。
加载优化
- 静态资源的压缩合并
- 静态资源缓存
- 使用CDN让资源加载更快
- 使用SSR(Server Side Render)后端渲染,数据直接输出到HTML中
渲染优化
- CSS放前面,JS放后面
- 懒加载(图片懒加载、下拉加载更多)
- 减少DOM查询,对DOM查询做缓存
- 减少DOM操作,多个操作尽量合并在一起执行
- 事件节流(频繁的操作合并成一个)
- 尽早执行操作(如DOMContentLoaded)
老板来催了,要赶紧开始搞事了,按照清单一步步来吧。
1. 加载优化
(1)静态资源的压缩合并
把多个文件压缩合并成一个,减少请求次数
<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
- 手动合并
- 构建工具合并
<script src="abc.js"></script>
(2)静态资源缓存
- 通过链接名称控制缓存,名称不变都从缓存中取文件
<script src="abc_1.js"></script>
- 只有内容改变的时候,链接名称才改变,才更新缓存
(3)使用CDN让资源加载更快
使用CDN会比个人服务器更快些,原因在这。
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
(4)使用SSR(Server Side Render)后端渲染
使用SSR(Server Side Render)后端渲染,数据直接输出到HTML中,不需要再用ajax去请求。
- 现在Vue React提出了这样的概念
- jsp php asp都属于后端渲染
2. 渲染优化
(1)CSS放前面,JS放后面
利用页面加载的原理可以解释。
-
CSS
放在head
里而不能放在body
里面,便于先加载CSS
然后一次性渲染完成(而不是先默认渲染再覆盖)。 -
JS
放在body
最下面,因为JS
会阻塞渲染。
(2)懒加载
举个栗子,渲染时img先赋值为一个很小的图片,再通过JS加载原图。
<img id="img1" src="preview.png" data-realsrc="src.png" />
<script type="text/javascript">
var img1 = document.getElementById('img1')
img1.src = img1.getAttribute('data-realsrc')
</script>
(3)缓存DOM查询
//未缓存DOM查询
var i
for (i=0; i< document.getElementsByTagName('p').length; i++){
// console.log(i)
//todo
//每次循环都要进行DOM查询,10个p标签就要查询10次
}
//缓存DOM查询
var pList = document.getElementsByTagName('p')
var i
for (i=0; i< pList.length; i++){
// console.log("缓存"+i)
//todo
//只需要查询一次缓存起来,以后的循环中不需要再进行DOM查询,节省时间
}
(4)合并DOM插入
var listNode = document.getElementById('list')
//插入10个li标签
var frag = document.createDocumentFragment(); //创建一个片段
var x, li;
for(x = 0; x < 10; x++){
li = document.createElement("li");
li.innerHTML = "List item" + x;
frag.appendChild(li);
}
listNode.appendChild(frag); //合并插入,和缓存的原理类似
(5)事件节流
//捕捉键盘弹起事件
var textarea = document.getElementById('text')
var timeoutId
textarea.addEventListener('keyup',function(){
if(timeoutId){
clearTimeout(timeoutId)
}
timeoutId = setTimeout(function(){
//触发change事件
},100)
//在100ms内连续按键的话,只触发一次change事件
})
有木有发现,缓存DOM查询、合并DOM插入、事件节流都是一个目的:减少能减少的一切DOM操作&触发事件操作。
(6)尽早执行操作
window.addEventListener('load',function(){
//页面的全部资源加载完(#阶段)才会执行,包括图片视频等
})
document.addEventListener('DOMContentLoaded',function(){
//DOM渲染完(&阶段)即可执行,此时图片、视频还可能没有加载完
})
这儿是可以运行的源代码。
优化完代码,鹿鹿提交了新版本上线,伸个懒腰 “终于可以下班了”。
盆友们,下期见~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。