这是我参与更文挑战的第13天,活动详情查看: 更文挑战
渲染流程图
首先,我们得先知道浏览器渲染的一个过程。如图
可以看出主要是这么几个步骤。
-
解析HTML,构建DOM树
-
解析CSS,生成CSS规则树
-
合并DOM树和CSS规则,生成render树
问题 1:CSS会阻塞什么?
CSS
不会阻塞 DOM
的解析
很明显dom的解析和css的加载是并行的,毫无关联。
CSS
阻塞页面渲染
虽然css不会阻塞dom的解析,但是我们可以发现,我们的render需要结合cssom和dom。两者缺一不可。如果css没有加载完,就没有生成cssom,就没办法生成render。就不用谈什么渲染了。
CSS加载会阻塞后面js语句的执行
当CSS后边跟着嵌入的JS的时候,该CSS就会出现阻止后边资源下载的情况。
解决方法:把嵌入的JS放在CSS前边
原因:浏览器会维持html中css和js的顺序,样式表必须在嵌入放入JS执行前先加载、解析完,而嵌入的JS会阻塞后边的资源加载,所以就会出现CSS阻塞
问题2:JS会阻塞什么?
JS 阻塞 DOM 解析,但浏览器会”偷看”DOM,预先下载相关资源。
浏览器遇到 <script>
且没有defer: 或async
属性的 标签时,会触发页面渲染,因而如果前面CSS资源尚未加载完毕时,浏览器会等待它加载完毕在执行脚本
所有浏览器在下载JS的时候,会阻止其他的一切活动(比如其他资源的下载,内容的呈现等等)。为了提高用户体验,新一代浏览器都支持并行下载JS,但是JS下载还是会阻止其他资源如(图片、css文件等等)
原因:浏览器为了防止出现JS修改DOM树,需要重构DOM树的情况,就会阻止其他资源的下载和呈现
嵌入JS会阻止所有内容的呈现,但是外部JS只会阻止其后内容的显示
嵌入的JS应该放在什么位置
-
放在底部,只会阻塞所有内容的呈现,但是不会则阻塞资源的下载(js放在前)
-
如果嵌入JS放在head中,则嵌入JS放在css头部
-
使用defer(能延迟执行,等到整个文档解析完再执行,但是不会延迟下载,浏览器遇到script就立即下载脚本)
-
不要在嵌入的JS中调用执行时间较长的函数,如果一定要用,可以用setTimeout来调用
-
动态脚本元素使用js动态创建HTML的几乎全部文档内容