您好、欢迎来到现金彩票网!
当前位置:ag视讯 > 复制数组 >

原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的

发布时间:2019-07-09 02:33 来源:未知 编辑:admin

  hello~各位亲爱的看官老爷们大家好。估计大家都听过,尽量将 CSS 放头部,JS 放底部,这样可以提高页面的性能。然而,为什么呢?大家有考虑过么?很长一段时间,我都是知其然而不知其所以然,强行背下来应付考核当然可以,但实际应用中必然一塌糊涂。因此洗(wang)心(yang)革(bu)面(lao),小结一下最近玩出来的成果。

  由于关系到文件的读取,那是肯定需要服务器的,我会把全部的文件放在 github 上,给我点个 star 我会开心!掘金上再给我点个 赞 我就更开心了~

  嗯!其实就延时啦。如果 CSS 或者 JS 文件名有 sleep3000 之类的前缀时,意思就是延迟 3000 毫秒才会返回这文件。

  关于 CSS,大家肯定都知道的是link标签放在头部性能会高一点,少一点人知道如果与link同时在头部的话,在上可能会更好。这是为什么呢?下面我们一起来看一下 CSS 对 DOM 的影响是什么。

  defer 属性相信大家也很熟悉了,MDN 对此的描述是用来通知浏览器该脚本将在文档完成解析后,触发 DOMContentLoaded 事件前执行。设置这个属性,能保证 DOM 解析后马上打印出 div。

  其实这一点,刚才的例子已经说明了,如果 CSS 不会阻塞页面阻塞渲染,那么 CSS 文件下载之前,浏览器就会渲染出一个浅绿色的 div,之后再变成浅蓝色。浏览器的这个策略其实很明智的,想象一下,如果没有这个策略,页面首先会呈现出一个原始的模样,待 CSS 下载完之后又突然变了一个模样。用户体验可谓极差,而且渲染是有成本的。

  因此,基于性能与用户体验的考虑,浏览器会尽量减少渲染的次数,CSS 顺理成章地阻塞页面渲染。

  答案是浏览器会转圈圈三秒,但此过程中不会打印任何东西,之后呈现出一个浅蓝色的 div,再打印出 null。结果好像是 CSS 不单阻塞了页面渲染,还阻塞了 DOM 的解析啊!稍等,在你打算掀桌子疯狂吐槽我之前,请先思考一下是什么阻塞了 DOM 的解析,刚才已经证明了 CSS 是不会阻塞的,那么阻塞了页面解析其实是 JS!但明明 JS 的代码如此简单,肯定不会阻塞这么久,那就是 JS 在等待 CSS 的下载,这是为什么呢?

  仔细思考一下,其实这样做是有道理的,如果脚本的内容是获取元素的样式,宽高等 CSS 控制的属性,浏览器是需要计算的,也就是依赖于 CSS。浏览器也无法感知脚本内容到底是什么,为避免样式获取,因而只好等前面所有的样式下载完后,再执行 JS。因而造成了之前例子的情况。

  所以,看官大人明白为何与link同时在头部的话,在上可能会更好了么?之所以是可能,是因为如果link的内容下载更快的话,是没影响的,但反过来的话,JS 就要等待了,然而这些等待的时间是完全不必要的。

  JS,也就是标签,估计大家都很熟悉了,不就是阻塞 DOM 解析和渲染么。然而,其中其实还是有一点细节可以考究一下的,我们一起来好好看看。

  其实那个数组操作时没意义的,只是为了让这个 JS 文件多花执行时间而已。之后把这个文件插入头部,浏览器跑一下。

  结果估计大家也能想象得到,浏览器转圈圈一会,这过程中不会有任何东西出现。之后打印出 null,再出现一个浅绿色的 div。现象就足以说明 JS 阻塞 DOM 解析了。其实原因也很好理解,浏览器并不知道脚本的内容是什么,如果先行解析下面的 DOM,万一脚本内全删了后面的 DOM,浏览器就白干活了。更别谈丧心病狂的 document.write。浏览器无法预估里面的内容,那就干脆全部停住,等脚本执行完再干活就好了。

  对此的优化其实也很显而易见,具体分为两类。如果 JS 文件体积太大,同时你确定没必要阻塞 DOM 解析的话,不妨按需要加上 defer 或者 async 属性,此时脚本下载的过程中是不会阻塞 DOM 解析的。

  而如果是文件执行时间太长,不妨分拆一下代码,不用立即执行的代码,可以使用一下以前的黑科技:setTimeout()。当然,现代的浏览器很聪明,它会“偷看”之后的 DOM 内容,碰到如link、和img等标签时,它会帮助我们先行下载里面的资源,不会傻等到解析到那里时才下载。

  这个细节可能不少看官大人并不清楚,其实这才是解释上面为何 JS 执行会等待 CSS 下载的原因。先上例子,HTML 内 body 的结构如下:

  这个例子也是很极端的例子,但不妨碍它透露给我们很多重要的信息。想象一下,页面会怎样呢?

  答案是先浅绿色,再浅灰色,最后浅蓝色。由此可见,每次碰到标签时,浏览器都会渲染一次页面。这是基于同样的理由,浏览器不知道脚本的内容,因而碰到脚本时,只好先渲染页面,确保脚本能获取到最新的 DOM 元素信息,尽管脚本可能不需要这些信息。

  感谢各位看官大人看到这里,希望本文对你有所帮助,有不同或更好意见的大佬,还望不吝赐教!谢谢

http://csyuntao.net/fuzhishuzu/818.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有