defer
属性相信大家也很熟悉了,MDN对此的描述是用来通知浏览器该脚本将在文档完成解析后,触发 DOMContentLoaded 事件前执行。设置这个属性,能保证DOM
解析后马上打印出div
。
之后将<link rel="stylesheet" href="/css/sleep3000-common.css">
插入HTML
文件的任一位置,打开浏览器,可以看到是首先打印出div
这个DOM
节点,过3s左右之后才渲染出一个浅蓝色的div
。这就证明了CSS
是不会阻塞 DOM
的解析的,尽管CSS
下载需要3s,但这个过程中,浏览器不会傻等着CSS
下载完,而是会解析DOM
的。
这里简单说一下,浏览器是解析DOM
生成DOM Tree
,结合CSS
生成的CSS Tree
,最终组成render tree
,再渲染页面。由此可见,在此过程中CSS
完全无法影响DOM Tree
,因而无需阻塞DOM
解析。然而,DOM Tree
和CSS Tree
会组合成render tree
,那CSS
会不会页面阻塞渲染呢?
CSS
阻塞页面渲染
其实这一点,刚才的例子已经说明了,如果CSS
不会阻塞页面阻塞渲染,那么CSS
文件下载之前,浏览器就会渲染出一个浅绿色的div
,之后再变成浅蓝色。浏览器的这个策略其实很明智的,想象一下,如果没有这个策略,页面首先会呈现出一个原始的模样,待CSS
下载完之后又突然变了一个模样。用户体验可谓极差,而且渲染是有成本的。
因此,基于性能与用户体验的考虑,浏览器会尽量减少渲染的次数,CSS
顺理成章地阻塞页面渲染。
然而,事情总有奇怪的,请看这例子,HTML
头部结构如下:
但思考一下这会产生什么结果呢?
答案是浏览器会转圈圈三秒,但此过程中不会打印任何东西,之后呈现出一个浅蓝色的div
,再打印出null
。结果好像是CSS
不单阻塞了页面渲染,还阻塞了DOM
的解析啊!稍等,在你打算掀桌子疯狂吐槽我之前,请先思考一下是什么阻塞了DOM
的解析,刚才已经证明了CSS
是不会阻塞的,那么阻塞了页面解析其实是JS
!但明明JS
的代码如此简单,肯定不会阻塞这么久,那就是JS
在等待CSS
的下载,这是为什么呢?
仔细思考一下,其实这样做是有道理的,如果脚本的内容是获取元素的样式,宽高等CSS
控制的属性,浏览器是需要计算的,也就是依赖于CSS
。浏览器也无法感知脚本内容到底是什么,为避免样式获取,因而只好等前面所有的样式下载完后,再执行JS
。因而造成了之前例子的情况。
所以,看官大人明白为何<script>
与<link>
同时在头部的话,<script>
在上可能会更好了么?之所以是可能,是因为如果<link>
的内容下载更快的话,是没影响的,但反过来的话,JS
就要等待了,然而这些等待的时间是完全不必要的。
JS篇
JS
,也就是<script>
标签,估计大家都很熟悉了,不就是阻塞DOM
解析和渲染么。然而,其中其实还是有一点细节可以考究一下的,我们一起来好好看看。
JS
阻塞 DOM
解析
首先我们需要一个新的JS
文件名为blok.js
,内容如下:
const arr = [];
for (let i = 0; i < 10000000; i++) {
arr.push(i);
arr.splice(i % 3, i % 7, i % 5);
}
const div = document.querySelector(‘div’);
console.log(div);
其实那个数组操作时没意义的,只是为了让这个JS
文件多花执行时间而已。之后把这个文件插入头部,浏览器跑一下。
结果估计大家也能想象得到,浏览器转圈圈一会,这过程中不会有任何东西出现。之后打印出null
,再出现一个浅绿色的div
。现象就足以说明JS
阻塞 DOM
解析了。其实原因也很好理解,浏览器并不知道脚本的内容是什么,如果先行解析下面的DOM
,万一脚本内全删了后面的DOM
,浏览器就白干活了。更别谈丧心病狂的document.write
。浏览器无法预估里面的内容,那就干脆全部停住,等脚本执行完再干活就好了。
对此的优化其实也很显而易见,具体分为两类。如果JS
文件体积太大,同时你确定没必要阻塞DOM
解析的话,不妨按需要加上defer
或者async
属性,此时脚本下载的过程中是不会阻塞DOM
解析的。
而如果是文件执行时间太长,不妨分拆一下代码,不用立即执行的代码,可以使用一下以前的黑科技:setTimeout()
。当然,现代的浏览器很聪明,它会“偷看”之后的DOM
内容,碰到如<link>
、<script>
和<img>
等标签时,它会帮助我们先行下载里面的资源,不会傻等到解析到那里时才下载。
浏览器遇到 <script>
标签时,会触发页面渲染
这个细节可能不少看官大人并不清楚,其实这才是解释上面为何JS
执行会等待CSS
下载的原因。先上例子,HTML
内body
的结构如下:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
最后:
总结来说,面试成功=基础知识+项目经验+表达技巧+运气。我们无法控制运气,但是我们可以在别的地方花更多时间,每个环节都提前做好准备。
面试一方面是为了找到工作,升职加薪,另一方面也是对于自我能力的考察。能够面试成功不仅仅是来自面试前的临时抱佛脚,更重要的是在平时学习和工作中不断积累和坚持,把每个知识点、每一次项目开发、每次遇到的难点知识,做好积累,实践和总结。
也是对于自我能力的考察。能够面试成功不仅仅是来自面试前的临时抱佛脚,更重要的是在平时学习和工作中不断积累和坚持,把每个知识点、每一次项目开发、每次遇到的难点知识,做好积累,实践和总结。