1

新版本上线了,头发也快长出来了。老板说用户反映页面加载慢,让鹿鹿继续做性能优化,那么问题来了,怎么搞?摸摸刚长出来的头发,鹿鹿准备去请教下大姥。

性能优化

大姥:前端做性能优化嘛,主要是两个原则

  • 多使用内存、缓存或者其他方法
  • 减少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渲染完(&阶段)即可执行,此时图片、视频还可能没有加载完
})

这儿是可以运行的源代码

优化完代码,鹿鹿提交了新版本上线,伸个懒腰 “终于可以下班了”。
盆友们,下期见~


鹿角包
175 声望8 粉丝

不苦程序媛