浅谈script标签中的async和defer
script
标签用于加载脚本与执行脚本,在前端开发中可以说是非常重要的标签了。
直接使用script
脚本的话,html
会按照顺序来加载并执行脚本,在脚本加载&执行的过程中,会阻塞后续的DOM
渲染。
现在大家习惯于在页面中引用各种的第三方脚本,如果第三方服务商出现了一些小问题,比如延迟之类的,就会使得页面白屏。
好在script
提供了两种方式来解决上述问题,async
和defer
,这两个属性使得script
都不会阻塞DOM
的渲染。
但既然会存在两个属性,那么就说明,这两个属性之间肯定是有差异的。
defer
如果
script
标签设置了该属性,则浏览器会异步的下载该文件并且不会影响到后续DOM
的渲染;
如果有多个设置了defer
的script
标签存在,则会按照顺序执行所有的script
;defer
脚本会在文档渲染完毕后,DOMContentLoaded
事件调用前执行。
我们做了一个测试页面,页面中包含了两个script
标签的加载,给他们都加上defer
标识。
P.S. 为了更直观,我们给script1.js
添加了1s
的延迟,给script2.js
添加了2s
的延迟。
下图是页面加载的过程&script
脚本的输出顺序。
不难看出,虽然script1
加载用时虽然比script2
短,但因为defer
的限制,所以Ta只能等前边的脚本执行完毕后才能执行。
async
async
的设置,会使得script
脚本异步的加载并在允许的情况下执行async
的执行,并不会按着script
在页面中的顺序来执行,而是谁先加载完谁执行。
我们修改测试页面如下:
遂得到了如下的结果,页面加载时长上,并没有什么变化,毕竟都是异步加载的脚本。
但是我们可以看到一个小细节,DOMContentLoaded
事件的触发并不受async
脚本加载的影响,在脚本加载完之前,就已经触发了DOMContentLoaded
。
我们接着修改测试页面。加载一个没有延迟的script
脚本,使得脚本可以即时的加载完毕。
我们要测试一下,如果async
脚本加载的足够快,是否会在DOMContentLoaded
之前就执行(这个实验是基于对async
的描述“在允许的情况下执行”的论证)。
同时为了保证测试的稳定性,我们在script
脚本引入的后边添加了数千个空的div
节点,用来延长文档的渲染时间。
执行结果不出所料,如果给async
一定的时间,是有可能在DOMContentLoaded
事件之前就执行的。
P.S. 从上图中左上角的火焰图中,我们也能看到,出现了多段的蓝色(更新:晚上写的时候懵了,紫色的才是渲染,蓝色的是解析)文档渲染。以及下边Console
的顺序。
说明的确,async
的执行是加载完成就会去执行,而不像defer
那样要等待所有的脚本加载完后按照顺序执行。
画几张图简要说明
网上有了不少这种类似的图,但是基本都是拿一个script就举例的
未免太过寒酸,so咱们来一个豪华版,来画一下多个脚本加载时的甘特图
就像近年来各大手机厂商,出新机都喜欢来一个X+X plus
拿四个不同的颜色来标明各自代表的含义
普通script
文档解析的过程中,如果遇到script
脚本,就会停止页面的渲染进行下载(但是并不会影响后续的解析,解析和渲染是两码事儿)。
资源的下载是在解析过程中进行的,虽说script1
脚本会很快的加载完毕,但是他前边的script2
并没有加载&执行,所以他只能处于一个挂起的状态,等待script2
执行完毕后再执行。
当这两个脚本都执行完毕后,才会继续渲染页面。
defer
文档解析时,遇到设置了defer
的脚本,就会在后台进行下载,但是并不会阻止文档的渲染,当页面解析&渲染完毕后。
会等到所有的defer
脚本加载完毕并按照顺序执行,执行完毕后会触发DOMContentLoaded
事件。
async
async
脚本会在加载完毕后执行。async
脚本的加载不计入DOMContentLoaded
事件统计,也就是说下图两种情况都是有可能发生的
推荐的应用场景
defer
如果你的脚本代码依赖于页面中的DOM
元素(文档是否渲染完毕),或者被其他脚本文件依赖。
例:
- 评论框
- 代码语法高亮
polyfill.js
async
如果你的脚本并不关心页面中的DOM
元素(文档是否渲染完毕),并且也不会产生其他脚本需要的数据。
例:
- 百度统计
如果不太能确定的话,用defer
总是会比async
稳定。。。
参考资料
测试代码存放处:https://github.com/Jiasm/research-script-tagclone
后执行npm start
即可运行。
调试推荐使用chrome
无痕模式(这样才不会在Performance
页签上看到不相关的插件数据)。
浅谈script标签中的async和defer的更多相关文章
- script标签中的async、defer属性
Script标签是我们常用的引用js脚本的一种方式. 撸代码的时候,我们常常只写src属性,直接忽略其他属性. 最近发现了2个可以利用的属性:async.defer. 顾名思义async就是异步,在不 ...
- 浅谈struts2标签中的2个非经常常使用的标签的使用方法(radio和select)
1.如图所看到的我们须要在前台的页面通过radio和select将相应的数据库中的数据显示到选项其中,这也是我们做项目中常常须要做的,动态的显示,而不是静态的显示. 首先我们须要在页面中导入strut ...
- script 标签里的 async 和 defer
无 async 和 defer 浏览器立即加载并执行指定脚本(读到即加载并执行),阻塞文档解析 async 脚本的加载执行和文档的加载渲染 并行. defer 脚本的加载和文档的加载渲染并行,但脚本的 ...
- 转:script中的async和defer
script中的async和defer defer: This Boolean attribute is set to indicate to a browser that the script is ...
- javaScript中的小细节-script标签中的预解析
首先介绍预解析,虽然预解析字面意思很好理解,但是却是出坑出的最多的地方,也是bug经常会有的地方,利用好预解析的特性可以解决很多问题,并且提高代码的质量及数量,浏览器在解析代码前会把变量的声明和函数( ...
- 转: 浅谈C/C++中的指针和数组(二)
转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组 ...
- 转:浅谈C/C++中的指针和数组(一)
再次读的时候实践了一下代码,结果和原文不一致 error C2372: 'p' : redefinition; different types of indirection 不同类型的间接寻址 /// ...
- 转载 浅谈C/C++中的static和extern关键字
浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.ext ...
- 浅谈C语言中的强符号、弱符号、强引用和弱引用
摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014- ...
随机推荐
- ServletResponse的一些知识点
ServletResponse* 服务器对浏览器做出的响应,将需要发送给浏览器的所有数据全部存放在此对象上.* 发送数据,使用流操作,将所需要的数据,存放在指定的流中,数据将显示到浏览器中* 字符流 ...
- 201521123003《Java程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4-1) 1.1 实验总结 我们利用Sca ...
- 201521123047 《Java学习笔记》第二周学习总结
1. 本周学习总结 -知道并了解到浮点数的误差关系,懂得运java.math.BigDecimal来进行浮点数的精确计算 -对于"="与"=="的区分 -字符串 ...
- [LeetCode]Count and Say 计数和发言
Count and Say 计数和发言 思路:首先要理解题意,可以发现后者是在前者的基础之上进行的操作,所以我们拿之前的结果作为现在函数的参数循环n-1次即可,接下来就是统计字符串中相应字符的个数,需 ...
- Mybatis第八篇【一级缓存、二级缓存、与ehcache整合】
Mybatis缓存 缓存的意义 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题. myba ...
- JVM菜鸟进阶高手之路四
转载请注明原创出处,谢谢! 由于很多的jvm分析最好是基于gc日志的,所以添加参数如下即可: -verbose:gc -XX:+HeapDumpOnOutOfMemoryError -XX:+Prin ...
- c语言中的内存浅析
1.栈(stack):存局部变量.函数,调用函数时会开辟栈区,函数结束时就自动回收,遵循后进先出的原则,从高地址向低地址增长. 2.堆(heap):malloc.realloc.calloc等开辟的内 ...
- jQuery: Callbacks
jQuery 中提供了一个Callback的工具类Callbacks,它提供了一个Callback Chain.使用它可以在一个chain上来执行相关操作.它也是jQuery中的ajax, Defer ...
- Spring Boot-------JPA——EntityManager构建通用DAO
EntityManager EntityManager 是用来对实体Bean 进行操作的辅助类.他可以用来产生/删除持久化的实体Bean,通过主键查找实体bean,也可以通过EJB3 QL 语言查找满 ...
- 2013 ACM/ICPC Asia Regional Hangzhou Online hdu4739 Zhuge Liang's Mines
Zhuge Liang's Mines Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...