script 加载方式

556 阅读2分钟

defer

deferscript标签具备的属性,类似告诉浏览器:不要等待我的下载,干你该干的事儿就好

defer 特性告诉浏览器不要等待它的下载。所以页面正常的处理HTML,构建DOM。
脚本会在“后台下载”,然后等待DOM 解析完成后,脚本才会执行。

Tips

  • 具有 defer属性的脚本,不会阻塞页面加载
  • 具有 defer 属性的脚本,需要等待页面DOM 解析完成后再执行,但是会在 DOMContentLoaded 事件之前

具有 defer 特性的脚本保持其相对顺序,就和常规脚本一样

<script src="1.js" defer />
<script src="2.js" defer />

脚本1和脚本2会并行下载,但是即使2在1之前下载完成,2也需要等待1加载完成再执行

async

async 也是script标签具备的属性,异步去加载执行脚本,不会阻塞页面流程(和defer类似) 但是和defer也有些不同点:

  • 浏览器不会因为async的脚本阻塞自己
  • async的脚本完全独立,彼此之家没有等待关系
  • DOMContentLoadedasync 也没有等待关系(可能在async脚本加载前执行,也可能之后)

动态插入脚本

还要一种方式就是动态插入script标签

const script = document.createElement('script')
script.src = '3.js'
document.body.append(script)

默认情况下动态插入的脚本也是异步的,这个其实很好理解,一旦动态插入,至少保证它不需要等别人,也没有人等它。 但你也可以手动加上defer 或者设置 async 为false

preload & prefetch

preloadprefetch 都是link标签的属性

<link rel="preload" href="4.js" as="script">
<link rel="prefetch" href="5.js" as="script">

两者控制的是浏览器什么契机去请求加载 script 资源,但是至于具体脚本的执行顺序,只有当遇到script标签加载的也是对应的JS的时候,浏览器才会直接将预先加载的JS执行掉。

preload是告诉浏览器,这些资源我一进页面就要用,优先去给我请求这些资源 prefetch 是在浏览器空闲的时候去请求这些资源

总结:

类型顺序所属标签DOMContentLoaded
async加载顺序 (脚本在代码中的顺序不重要,先加载完的先执行)script彼此独立,没有等待关系
defer文档顺序(脚本在代码中写的顺)scriptDOM解析后,DOMContentLoaded 之后
preload优先下载,但不涉及到执行(具体执行顺序依赖对应的script的顺序和加载方式)link-
prefetch浏览器空闲时请求下载,但不涉及到执行(具体执行顺序依赖对应的script的顺序和加载方式)link-