一文搞懂js和css是否阻塞dom解析和渲染(干货)

1,609 阅读3分钟

前序

通常我们把script标签放在body尾部,link标签放在head头部,通过CDN引入第三方库时,放在link标签前面

概述

  • CSS不会阻塞DOM解析,但是会阻塞DOM渲染,严谨一点则是CSS会阻塞render tree的生成,进而会阻塞DOM的渲染
  • JS会阻塞DOM解析
  • CSS会阻塞JS的执行
  • 浏览器遇到<script>标签且没有deferasync属性时会触发页面渲染
  • Body内部的外链CSS较为特殊,会形成FOUC(样式闪烁)现象,请慎用

css不会阻塞DOM解析,会阻塞dom渲染

  • DOM树和CSSOM树的解析是互不影响的,因此css不会阻塞页面的解析
  • 但是由于render树的生成是依赖DOM树和CSSOM树,因此CSS必然会阻塞DOM的渲染
  • css会阻塞rrender树的生成,进而会阻塞dom的渲染

js会阻塞dom解析

  • first paint
  • 改变dom

css会阻塞js的执行

  • 如果js脚本中是获取dom元素的css样式属性,为了获取到最新的正确的样式,需要所有的css加载完成,否则获取的样式可能是错误的或者不是最新的
  • 要等到js脚本前面的css加载完成,js才能再执行
  • 所以一般cdn引入第三方库的script一般放在link之前

js触发页面渲染

  • 浏览器解析DOM时,虽然是一行一行地向下执行,但是它会预先加载具有引用标记的外部资源(例如带有src标记的script标签)
  • 在解析到此标签的时候,则无需再去加载,直接运行,以此提高运行效率
  • 浏览器无法预先知道脚本的具体内容,因此碰到script标签时,只好先渲染一次页面,确保script脚本内能获取到dom最新的样式
  • 如果在决定渲染页面时,还有尚未加载完成的css文件,只能等待其加载完成再去渲染页面

body内的CSS(link)

  • body内的css属于特殊情况,会因浏览器的差异,呈现不同的表现形式,这种现象叫做FOUC(样式闪烁),代码中应当尽量避免

script标签中async和defer的区别

defer

  • 脚本被延迟到整个页面都解析完毕后再运行(立即下载,但延迟执行)
  • defer属性仅适用于外部脚本(用src引入的脚本),浏览器会忽略行内脚本的defer属性
  • 若多个script含defer属性,会按照出现次序执行
  • 不是所有浏览器都支持这个属性,因此把推迟执行的脚本文件放在body底部比较好(IE4、Firefox 3.5、Safari 5 和 Chrome 7 支持)

async

  • 与defer类似的是,它们都适用于外部脚本,都会告诉浏览器立即开始下载
  • 标记为async的脚本并不保证能按照它们出现的次序执行

image.png

  • 既没有defer也没有async,则浏览器遇到script标签时,会立即加载并执行指定的脚本,执行完毕之后,才继续解析后面的标签
  • 有async属性,浏览器遇到该script标签时,加载脚本的过程与解析后面标签的过程同时进行,加载完毕后,立即执行该脚本
  • 有defer属性,浏览器遇到该script标签时,加载脚本的过程与解析后面标签的过程同时进行。但是执行脚本的过程,在解析完所有元素之后才执行。(加载完脚本后,将执行推迟到页面解析完之后)

关于本文:
作者:Amethyst紫宣
来源:blog.csdn.net/Amethystlry…

后言

感兴趣的小伙伴可以浏览下以下系列相关文章,后续会深入浏览器的解析渲染进行展开(欢迎点赞+关注)

文章链接