<script>标签
script
元素最简单用法就是通过直接在页面嵌入 JS 代码或者通过加载外部脚本文件。而且大家都知道浏览器解析文档时遇到script
会依次等代码下载、执行完以后才会继续解析,因此现在Web应用程序一般都会把引用的JS代码放在<body>
元素的后面。
所以在HTML规范
中为了解决这个引入顺序问题,在script
标签上提供了async
和defer
这两个属性,使得文档解析到script
时不会发生阻塞。
defer 延迟脚本
加入defer属性后,即使把<script>
标签放入<head>
也不会阻塞后面DOM的解析,而且脚本会延迟到整个DOM解析完后在去执行。也就是<script>
标签加入defer属性会告诉浏览器立即下载脚本,但是延迟执行脚本
。
先看测试用例:
Chrome加载面板分析:
1、可以看到主进程的Parse HTML
并不会受<script>
标签影响,网络进程还是会立即去加载脚本资源。
2、多个设置了defer属性
的script标签,会按照文档中script放置顺序执行内容(即使前置的script加载耗时更长
)。
3、脚本内容会在HTML解析完毕后,DOMContentLoaded
事件调用前执行。
最终打印测试验证:
async 异步脚本
<script>
标签加入async属性会告诉浏览器立即下载脚本,哪个脚本先加载完就先执行,而且是加载完就立马执行
。如果有DOM正在解析,会阻塞解析。
测试用例:
Chrome加载面板分析:
1、DOMContentLoaded事件的触发并不受async
脚本加载的影响,async
脚本会在load事件调用前执行。
2、这里文档解析太快没体现出来,其实DOMContentLoaded
事件调用跟async
脚本执行顺序是不定的。
打印测试验证:
<link>标签
prefetch
prefetch是一种浏览器机制,利用浏览器空闲时间来下载后续可能需要使用的资源。在浏览器完成当前页面的加载后开始静默地拉取指定的文档并将其存储在缓存中。
使用方式:
<link rel="prefetch" href="xxx" />
测试用例:
Chrome Network面板分析:
可以看到
link prefetch
出现了coffee.jpg的加载请求。后续通过img src
再次请求coffee.jpg时,直接就通过prefetch cache
获取了。所以验证了浏览器在空闲时间预先加载资源,真正使用时直接从浏览器缓存中快速获取。
preload
顾名思义,preload就是希望浏览器尽早的请求资源,且不阻塞正常的onload。
使用方式:
<link rel="preload" href="xxx" as="xxx"/>
测试用例:
Chrome Network面板分析:
可以发现脚本的加载时机提前了,在浏览器开始解析html后很快就进行了加载。
注意:preload link必须设置as属性来声明资源的类型(font/image/style/script等),否则浏览器可能无法正确加载资源。
对于字体文件或者可以加载的跨域资源需要加上crossorigin属性。