当HTML解析器解析HTML,如果遇到script
标签,普通的script
标签会暂停对DOM解析渲染,因为该脚本可能会修改DOM。
这里有三种情况:普通脚步、defer、async。 ==<font color=red >defer、async只对外联script脚本文件有效, 内联script脚本设置无效。</font>==
问:
script
标签总是会触发Paint吗?回答:
script
标签时,会触发一次Paint,浏览器会将script
标签之前的元素渲染出来。但也并不是所有的script
标签都会触发Paint。head
中的script
标签是不会触发的,毕竟此时body
还没有解析,触发Paint也看不到任何内容。 inline(内联:将代码直接嵌入到HTML文档的元素中,而不是通过外部文件引用的方式) 的script
也不会触发Paint。因此,建议script
标签放在body
结束标签之前,这样不会不会阻塞页面整体内容的DOM解析和渲染。
DOMContentLoaded
、 loaded
事件2、defer,defer
属性的script
标签时,则脚本的下载则在后台运行,下载不会阻止DOM解析渲染defer
属性的script
标签,则在后台并行下载defer
脚本下载完毕并按照顺序执行,执行完毕后会触发DOMContentLoaded
事件。defer
脚本下载较慢,在下载完前, 页面解析渲染已完毕; 等所有的defer
脚本下载完后, 才按照顺序执行defer
脚本。执行完毕后会触发DOMContentLoaded
事件。3、asyncasync
属性的script
标签时,则脚本的下载则在后台运行,下载不会阻止DOM解析渲染async
属性的script
标签,则在后台同时并行下载async
脚本的执行会阻止页面的解析渲染link
标签并不阻塞DOM的解析,但会阻塞DOM的渲染。浏览器并行解析生成DOM Tree 和 CSSOM Tree,当两者都解析完毕,才会生成render tree,页面才会渲染。所以应尽量减小引入样式文件的大小,提高首屏展示速度。
注意:案例中CSS资源为外网资源,所以并不会直接就加载出来,可以在页面看到渲染的过程,当然可以直接开vpn,css资源几乎秒加载,页面也秒渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
setTimeout(() => {
console.log(document.getElementById('num'));
}, 0);
document.addEventListener('DOMContentLoaded', () => {
console.log('dom parse done');
})
</script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.css">
</head>
<body>
<div id="num">
i am content a.
</div>
<div>
i am content b.
</div>
</body>
</body>
</html>
初始加载页面的时候,控制台打印出来两条数据,但是页面并没渲染,此时CSS资源正在加载中
之后CSS资源一直加载,直到加载失败,页面才渲染完成,说明,link标签加载CSS资源时阻止了页面渲染
JS运行时,有可能会请求样式信息,如果此时还没有加载和解析样式,js就有可能会得到错误的回复,产生很多问题。因此浏览器在link
标签的加载和解析过程中,会禁止脚本运行。
<!DOCTYPE html>
<html lang="en">
<head>
<tilte>title</title>
<script>
console.log(Date.now());
</script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.css">
<script>
console.log(Date.now());
</script>
</head>
<body>
<div id="num">
i am content a.
</div>
<div>
i am content b.
</div>
</body>
</body>
</html>
初始页面加载,此时CSS资源正在加载中,所以body中的内容还没渲染出来,并且link
标签下的script
中的console
也还未执行,所以说,link标签加载CSS资源时也阻塞的JS的执行
之后,因为CSS资源加载失败,所以开始执行下面的script
,并且打印出console
内容-当前时间。
<html>
<head>
<tilte>title</title>
<!--大文件,加载时间长-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.css">
</head>
<body>
<div>
i am content a.
</div>
<!--js小文件,加载时间短-->
<script src='test.js'></script>
<div>
i am content b.
</div>
</body>
</html>
页面初始加载时,CSS资源一直在加载,body
中的script一直没有加载出来,可以看到控制台并没有打印任何东西。所以说link
标签会阻止JS执行
当CSS资源加载完成或者加载失败后就执行了script
脚本,可以看到控制台打印出来js执行完毕
,且此时页面已经渲染出来
<link href="a.css" rel="stylesheet" type="text/css">
<style>
@import url('b.css');
</style>
link
功能较多,可以定义 RSS、Rel 等,而@import
只能用于加载 css;link
标签让浏览器知道这是个样式表文件,html的解析和渲染不会暂停,css文件的加载是同时进行的,这不同于在style标签里面的内置样式;@import
添加的样式是在页面载入之后再加载,这可能会导致页面因重新渲染而闪烁。@import
会影响浏览器的并行下载,使得页面在加载时增加额外的延迟,增添了额外的往返耗时,而且多个@import
可能会导致下载顺序紊乱。比如:
一个css文件index.css
包含了以下内容:@import url(“reset.css”)
,那么浏览器就必须先把index.css
下载、解析和执行后,才下载、解析和执行第二个文件reset.css
link
支持DOM操作改变样式,由于 DOM 方法是基于文档的,无法使用@import
的方式插入样式@import
是 CSS2.1提出的语法,老版本的浏览器可能不支持;link
标签作为 HTML 元素,不存在兼容性问题。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。