现象: 用户体验差 网页太卡打不开(卡、慢) 服务器带宽流量(成本) 服务器压力
从哪处理:各处的缓存 地址缓存 减少DNS的解析请求、预解析DNS(不是"解析DNS") TCP缓存 HTTP缓存机制(HTTP请求、HTTP协议、CDN缓存、浏览器缓存)文件打包编译压缩CSS、JS阻塞,白屏和FOUC+defer和ansync函数防抖+函数节流 懒加载和预加载
蚂蚁金服如何把前端性能监控做到极致?
页面性能优化办法有哪些? · Issue #9 · ljianshu/Blog
方应杭:「每日一题」你是如何做性能优化的?
【前端词典】 【前端词典】从输入 URL 到展现涉及哪些缓存环节(非常详细)
你真的了解回流和重绘吗 - 掘金
css加载会造成阻塞吗? - 掘金
javascript性能优化 - 掘金
防抖节流与前端性能优化
函数节流和防抖 · Issue #43 · ljianshu/Blog
懒加载和预加载 · Issue #8 · ljianshu/Blog
从输入 URL 到展现涉及哪些缓存环节(非常详细)
深入理解浏览器的缓存机制
例如:想优化公司的网站访问速度
大概的思路:减少HTTP请求,同时设置静态文件缓存时间、压缩情况、保持持久的连接时间等参数,但这些东西,又需要你系统了解HTTP协议。
前言
之前听过芳芳说过,你要做一件事需要明确目的,就好比每天吃的三餐也是存在目的,只不过是因为我们习惯了它的存在,从而忽略吃三餐的目的其实就是让我们活着。
回归到”为什么要做前端性能优化工作“这个问题上?先从我们最熟悉的打开网页时要等待时间这件事说起,从“时间就是生命”这个角度来说,白白等时间浪费掉,导致的结果就是损耗生命。
明确了“不想损耗生命“这个目的,就要从实际的场景中思考,导致网页加载时间过长、过卡,就能先想到打开网页的流程中某些情况没有优化导致:
1、从输入url开始产生需要缓存的地方
2、DNS查询——优化:减少对单个域名的查询时间或对多个域名进行查询
3、浏览器发送请求缓存优化:发送请求时——优化:减少对文件的请求,比如可以压缩、合并文件,添加缓存
4、服务器响应缓存优化:服务器的响应——优化:(服务器的优化就有点复杂)
5、解析时优化:解析HTML、CSS、JS时 ——减少或优化一些无用代码,减少解析时间
6、渲染优化:渲染HTML、CSS、JS、图片时 —— 避免使用低效代码对性能的损耗
(一)缓存优化
从输入 URL 到展现涉及哪些缓存环节(非常详细)
一文读懂前端缓存
一、从缓存开始谈起
之前就有针对浏览器的缓存机制写了一篇文章,让你知道如何设置对应参数值(通常是设置时间),浏览器什么时候使用了缓存文件?而什么时候需要请求服务器响应接收缓存?感兴趣的朋友可以在专栏中再来看看。
1、缓存可以带来什么好处
从实战的经验来看,想象一下从URL的输入开始起你经历过的缓存
有了缓存,减少冗余数据传输,节省流量
有了缓存,可从本地获取缓存文件,减少对重复代码的请求,节省带宽,提高页面加载速度,和网页打开速度
有了缓存,可以缓解服务器请求过程中产生的阻塞情况
有了缓存,就相当于在浏览器有个备份,可以加快响应速度
总之,缓存带来的直观感受就是网页打开速度更快、网页资源加载的速度更快。缓存之后,必然是减少了大量的数据、资源的请求对服务器带来的压力。2、从哪里进行缓存
我先从我接触过的实际场景说起,当然应该这中间还有其他缓存,我没接触到:
(1)从在网址地址栏中输入URL里缓存
(2)进行DNS查询时就会开启缓存
(3)TCP连接时进行握手时,发送和接收的缓存
(4)HTTP请求缓存
(关于缓存具体信息,会单独再写一篇文章)
二、从 DNS查询 和 预解析DNS 谈起
1、先谈DNS查询
之前我们在“输入URL到页面展现”那篇文章稍微谈过利用DNS查找IP的事情,DNS寻址的这个过程本身就是一个复杂的寻址过程。(如果这一块没有讲清楚,老司机们请不吝指教)
2、DNS预解析(DNS-prefetch)
这是一个隐藏在浏览器的前端优化手段,主要体现在这两点:
- 减少DNS解析次数
- 进行DNS预解析
预解析的实现:
(1)用meta信息来告知浏览器, 当前页面要做DNS预解析: <meta http-equiv="x-dns-prefetch-control" content="on" />
(2)在页面header中使用link标签来强制对DNS预解析: <link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
注:dns-prefetch 需慎用,多页面重复 DNS预解析 会增加重复DNS查询次数。
三、TCP也涉及缓存
四、HTTP缓存
1、浏览器缓存
2、CDN缓存
3、浏览器缓存
(二)文件压缩编译
(三)CSS、JS解决阻塞问题
JS性能优化-掘金
一、JS
1、核心JS代码
2、非核心JS代码引入方式和异步机制
二、CSS和JS的阻塞渲染 采取的优化
这边只讲一些需要优化的现实状况,涉及深入原理
1、CSS加载造成阻塞 ?参考:css加载会造成阻塞吗? - 掘金先给个最终结论:CSS加载不会阻塞DOM树解析,但会阻塞DOM树渲;CSS加载会阻塞后面JS语句执行注意:不知道有没有人注意我描述的字眼不同:解析、加载、渲染。
一般情况下,解析,是解析HTML内容;加载,一般是CSS加载、页面加载,这个时候页面还处在如样式加载、图片加载的阶段,但还没渲染到页面;渲染,此时,就是某个环节完成之后,才会进行渲染,如解析完渲染,加载完渲染等等。
以Chrome为例,先在Chrome控制台设置一下网速(百度一下),资源的下载速度上限就会被限制成20kb/s。(1)CSS加载会阻塞DOM树的解析渲染吗?
<!DOCTYPE html>
<html lang="en">
<head>
<title>css阻塞</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
h1 {
color: red !important
}
</style>
<script>
function h () {
console.log(document.querySelectorAll('h1'))
}
setTimeout(h, 0)
</script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<h1>这是红色的</h1>
</body>
</html>
假设结果:
CSS加载会阻塞DOM树解析和渲染假设画面:按道理在 CSS 还没加载完前,下面的内容不会被解析渲染,那么我们一开始看到的应该是白屏,h1 不会显示出来。并且此时 console.log 结果应该是一个空数组。实际结果:
如下图
由上图我们可以看到,当CSS还没加载完成的时候,h1并没有显示,但是此时控制台输出如下
由上图,我们也可以看到,当CSS还没加载出来的时候,页面显示白屏,直到CSS加载完成之后,红色字体才显示出来,也就是说,下面的内容虽然解析了,但是并没有被渲染出来。所以,CSS加载会阻塞DOM树渲染。
评价该机制:有过项目经验的人估计马上反应,如果是对DOM节点和CSS样式加载操作,一般都是冲着优化性能去的。原作者认为这是浏览器的其中一种优化机制。当加载CSS时,可能会修改下面DOM节点的样式,如果CSS加载不阻塞DOM树渲染的话,那么当CSS加载完之后,DOM树可能又得重新重绘或者回流了,这就造成了一些没必要的损耗。所以,干脆先将DOM树结构解析完,把可以做的工作做完,然后等你CSS加载完后,再根据最终的样式来渲染DOM树,这种做法性能方面确实会比较好一点。
由此得出:CSS加载不会阻塞DOM树解析,但是会阻塞DOM树渲染。
(2)CSS加载会不会阻塞js执行呢?
<!DOCTYPE html>
<html lang="en">
<head>
<title>css阻塞</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
console.log('before css')
var startDate = new Date()
</script>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<h1>这是红色的</h1>
<script>
var endDate = new Date()
console.log('after css')
console.log('经过了' + (endDate -startDate) + 'ms')
</script>
</body>
</html>
假设结果:
css加载会阻塞后面的js运行预期画面:
在link后面的js代码,应该要在css加载完成后才会运行实际结果:
如下图
由上图我们可以看出,位于css加载语句前的那个js代码先执行了,但是位于css加载语句后面的代码迟迟没有执行,直到css加载完成后,它才执行。这也就说明了,css加载会阻塞后面的js语句的执行。
详细结果看下图(css加载用了5600+ms):
结论
由上所述,我们可以得出以下结论:
- css加载不会阻塞DOM树的解析
- css加载会阻塞DOM树的渲染
- css加载会阻塞后面js语句的执行
解决CSS和JS的阻塞渲染
(1)通过 最佳放置顺序 解决
- CSS,尽可能放在头部,使用 link 标签将样式表放在顶部,通常放在 <head>
- JS ,将JS放在底部,通常放在<body>底部
(2)JS解决阻塞:defer和async
2、产生白屏和FOUC现象
白屏,加入CSS没有解析和加载完成,或者JS加载时机过晚(渲染进程被阻塞),都会造成白屏现象(白屏是页面渲染的其中一个呈现结果),HTML解析内容完成之后,样式和交互未出现的话,页面则会出现一片空白,等到 CSS和JS完全解析、加载完毕之后,页面才会渲染出来。
FOUC,一般是CSS还没加载完成前,HTML内容已经解析、渲染完成。等到CSS解析且加载完毕后,浏览器再次渲染。
3、重绘(Repaint )和重排( Reflow)
浏览器渲染过程中引起的问题
Repaint问题 : 重新绘制。将CSS样式改变的话,其他元素并未改变,只需要重新绘制某一处就行。 Reflow问题: 重新回流,重新计算。即自身位置发生变化,给其他元素带来了影响,要重新进行计算。
(四)函数防抖和函数节流
一、函数防抖
带着一起走
二、函数节流