-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第199题:CSS 会阻塞 DOM 解析吗? #510
Comments
|
浏览器的渲染浏览器的渲染流程如下: 图:WebKit 主流程 图:Mozilla 的 Gecko 呈现引擎主流程(3.6) 结合上图,一个完整的渲染流程如下:
值得注意的是: 关键的点在于上述的 4 步并不是以严格顺序执行的。渲染引擎会以最快的速度展示内容,也就是说,浏览器一边解析 HTML,一边构建渲染树,构建一部分,就会把当前已有的元素渲染出来。如果这个时候外部样式并没有加载完成,渲染出来的就是浏览器默认样式了。 其它阶段也是如此。由于浏览器会尝试尽快展示内容,所以内容有时会在样式还没有加载的时候展示出来。这就是经常发生的FOCU(flash of unstyled content)或白屏问题。 CSS 加载不会阻塞 DOM 树的解析由浏览器的渲染流程图可知,DOM 解析和 CSS 解析是两个并行的进程,所以 CSS 加载不会阻塞 DOM 树的解析 CSS 加载会阻塞 DOM 树的渲染Render Tree是依赖于 DOM Tree 和 CSSOM Tree 的,所以无论 DOM Tree 是否已经完成,它都必须等待到 CSSOM Tree 构建完成,即 CSS 加载完成(或 CSS 加载失败)后,才能开始渲染。 因此,CSS加载是会阻塞 DOM 树的渲染 <head>
<script>
document.addEventListener('DOMContentLoaded', () => {
var p = document.querySelector('p')
console.log(p)
})
</script>
<link rel="stylesheet" href="./static/style.css?sleep=3000">
</head>
<body>
<p>hello world</p>
</body> 案例来源:关于 JS 与 CSS 是否阻塞 DOM 的渲染和解析 CSS 的加载并没有阻塞 DOM 树的解析,p 标签是正常解析的,但 p 标签加载完后,页面是迟迟没有渲染的,是因为 CSS 还没有请求完成,在 CSS 请求完成后,hello world 才被渲染出来,所以 CSS 会阻塞页面渲染
CSS 加载会阻塞其后的 JS 执行由浏览器的渲染流程图可知,JS 的加载、解析与执行会阻塞 DOM 的构建,也就是说,在构建 DOM 时,HTML 解析器若遇到了 JS,那么它会暂停构建 DOM ,将控制权移交给JS引擎,等 JS 引擎运行完毕,浏览器再从中断的地方恢复 DOM 构建。 这也是建议将 script 标签放在 body 标签底部的原因。 由浏览器的渲染流程图可知,DOM 和 CSSOM 的构建是互不影响,但如果在 JS 脚本前引入外部 CSS 文件喃? <html>
<head>
<link href="theme.css" rel="stylesheet">
</head>
<body>
<div>hello world</div>
<script>
console.log('hello world')
</script>
<div>hello world</div>
</body>
</html> 它的执行流程: 此时 CSS 也阻塞 DOM 的生成 这是因为 JS 不只是可以改 DOM ,它还可以更改样式,也就是它可以更改 CSSOM 。而不完整的 CSSOM 是无法使用的, JS 中想访问 CSSOM 并更改它,那么在执行 JS 时,必须要能拿到完整的CSSOM。 所以就导致了一个现象,如果浏览器尚未完成 CSSOM 的下载和构建,而我们却想在此时运行脚本,那么浏览器将延迟脚本执行和 DOM 构建,直至其完成 CSSOM 的下载和构建。也就是说,在这种情况下,浏览器会先下载和构建 CSSOM ,然后再执行JS脚本,最后在继续构建 DOM 。 如果也有 JS 加载喃? <head>
<script>
document.addEventListener('DOMContentLoaded', () => {
var p = document.querySelector('p')
console.log(p)
})
</script>
<link rel="stylesheet" href="./static/style.css?sleep=3000">
<script src="./static/index.js"></script>
</head>
<body>
<p>hello world</p>
</body> HTML 文件中包含了 CSS 的外部引用和 JS 外部文件,HTML 同时发起这两个文件的下载请求,不管 CSS 文件和 JS 文件谁先到达,都要先等到 CSS 文件下载完成并生成 CSSOM,然后再执行 JavaScript 脚本,最后再继续构建 DOM,构建布局树,绘制页面。 所以一般将 如何优化渲染流程即如何减少白屏时间?
|
为什么 link css 放在body 中间,会造成 DOM 解析阻塞和渲染阻塞?chrome 92 |
大佬你可能要改了,刚刚测试了下,CSS 会阻塞 DOM 解析,当 link-in-body |
可以参考这个,页面加载时会被 JS 和 CSS 阻塞吗? |
css 阻止渲染是为了防止样式闪烁,这点三大浏览器都一样,只不过对比 link in body 情况 chrome、edge 选择组织解析 DOM,不组织渲染,这样同样会有可能样式闪烁,好处就是,渐进式渲染页面内容给用户看,这就属于特殊行为了。最好还是统一路径放在 head。 |
#所以一般将 <script> 放在 标签前面 |
No description provided.
The text was updated successfully, but these errors were encountered: