当前位置: 首页 > Web前端 > CSS

关于外部样式表你可能不知道的事情

时间:2023-03-30 19:14:32 CSS

singsong:文中的demo点这里??请参考github上的最新内容??在讲解之前先来看一道题。如下图,外部样式表会不会阻塞HTML解析(不要看答案,自己思考实验):通过DevTools->network:如上图,indexcss.css不会阻止HTML解析,因为DOMContentLoaded时间线在indexcss.css之后。但是如果我在indexcss.css后面加一个script标签(不能为空),结果会一样吗?通过DevTools->network:如上图,在indexcss.css后添加script标签(不能为空)后,DOMContentLoaded时间线位于indexcss.css后。说明这里的indexcss.css是阻塞HTML解析的。查阅相关资料,发现如下描述:另一方面,样式表有不同的模型。从概念上看,由于样式表不会更改DOM树,因此没有理由等待它们并停止文档解析。但是,脚本在文档解析阶段要求样式信息存在一个问题。如果尚未加载和解析样式,脚本将得到错误的答案,显然这会导致很多问题。这似乎是一个边缘案例,但很常见。当样式表仍在加载和解析时,Firefox会阻止所有脚本。WebKit仅在脚本试图访问某些可能受未加载样式表影响的样式属性时才阻止脚本。是的:样式表不修改DOM树,没有理由为了解析样式表而阻塞文档解析(即样式表不阻塞文档解析)。但是如果有脚本在解析文档的过程中需要访问样式信息,为了保证访问样式信息的正确性。Firefox会阻止所有脚本,直到样式表被下载和解析。另一方面,WebKit仅在访问尚未加载和解析的样式属性时才阻止脚本。也就是说style-sheet不会直接阻塞文档解析,它只是阻塞脚本的解析和执行,从而导致style-sheet间接阻塞文档解析。如果脚本设置为非阻塞呢?这可以通过将aysnc属性设置为脚本标签来实现。你可能想知道为什么不使用defer?async和defer脚本都立即开始下载而不暂停解析器,并且都支持可选的onload处理程序来解决执行初始化的常见需求,这取决于脚本。async和defer之间的区别在于脚本何时执行。每个异步脚本在完成下载后和窗口的加载事件之前会在第一次机会时执行。这意味着异步脚本有可能(并且很可能)不会按照它们在页面中出现的顺序执行。另一方面,延迟脚本保证按照它们在页面中出现的顺序执行。该执行在解析完全完成之后但在文档的DOMContentLoaded事件之前开始。大概意思是:脚本开头的async和defer特性下载的时候,不会阻塞文档解析。并且都支持一些初始化工作的onload事件回调处理。此外,它们都不适用于无法调用document.write()的内联脚本。两者的区别:具有异步特性的脚本会在脚本下载后立即执行,在加载事件之前执行,因此不能保证脚本在文档中出现的顺序被执行。具有延迟功能的脚本将按照它们在文档中出现的顺序在文档被解析之后和DOMContentLoaded事件之前执行。所以这里设置了async属性,没有设置defer属性。为了尽早触发DOMContentLoaded事件,因为defer会延迟DOMContentLoaded事件的触发。给脚本标签添加异步特性:ViaDevTools->network:当然这里也可以使用mediaquerymedia让style-sheet异步加载:ViaDevTools->network:总结:默认情况下,style-sheet不会阻塞document解析。style-sheet只会阻止脚本脚本的解析和执行。由于script脚本需要访问style-sheet的样式信息,为了保证样式信息的正确性,script脚本需要等待style-sheet的下载和解析。结果,样式表间接地阻止了文档解析。样式表可以通过媒体查询媒体异步加载。为脚本设置aysnc特性,实现脚本的异步加载,加速文档解析。参考文章:分析关键渲染路径性能破译关键渲染路径浏览器的工作原理:现代网络浏览器的幕后