资源提示符
刀刀
4/7/2025
0 字
0 分钟
一个项目打包后的 index.html
会生成很多 link
和 script
标签链接。这些链接都会加上一些 rel
属性,比如 rel="prefetch"
或者 rel="preload"
。这个 prefetch
和 preload
都被统称为资源提示符。
资源提示符不仅上面两个,还包括 async
、defer
、preconnect
、prerender
等。后两者不常见,这里不做介绍。
async 和 defer
这两个资源提示符都是作用于 script
标签的。下面来对比一下不用两者提示符、分别使用两者提示符浏览器解析 script
标签的区别。
正常情况
从上图可以看出,在啥提示符都不使用的情况下,浏览器会先正常解析 DOM元素。当看到
script
标签时会开启另一个网络线程下载相关 JS,在此期间它会一直等待,直到 JS 下载完成并执行。如果 JS 下载时间过长,那么页面渲染就会卡住,直到 JS 下载并执行完成。这就是页面堵塞。因此在之前
script
标签都是放到body
标签的底部,确保页面 DOM 元素渲染完毕后再执行。但是这样并不是最好的办法,因为 JS 下载时间过长,浏览器还是会需要一定时间去下载等待,因此这段堵塞时间还是需要优化。async
情况接着看添加
async
提示符后的情况。从上图可以看出,当浏览器遇到添加了async
提示符的script
标签时,会异步下载 JS 文件,此时页面的 DOM 渲染不会中断停止。直到 JS 请求完毕后再去执行该 JS 文件,执行完后继续渲染 DOM。但是这种方式也有缺点,就是 JS 执行顺序无法保证。如果 JS 文件之间存在依赖关系,那么使用
async
提示符就会导致 JS 执行顺序混乱,从而报错。若该 JS 文件使用到了 DOM 元素,那么 DOM 元素可能还未渲染完毕,因此无法获取到对应 DOM 元素从而报错。defer
情况最后看
defer
,这个提示符和async
提示符类似,都是异步下载 JS 文件。但是defer
提示符会保证 JS 文件的执行顺序,并且 DOM 元素渲染完毕后再执行 JS 文件。因此defer
提示符是解决页面堵塞最好的办法。额外注意的是,添加了
defer
提示符的 JS 文件运行时间点是在触发DOMContentLoaded
事件之前。
prefetch 和 preload
这两个资源提示符都是作用于 link
标签的。二者都是预先加载资源,都不会影响 DOM 解析,二者主要的区别是优先级。
如果使用的是 preload
,那么他的优先级是最高的,相当于告诉浏览器你要尽快下载完成,浏览器会优先加载该资源。
如果使用的是 prefetch
,那么他的优先级是较低的,相当于告诉浏览器这里有资源在你有空再下载就行,浏览器会在空闲时间才会去加载该资源。
因此当项目一开始需要下载的资源很多,而用户可能不会用到这些资源时,就可以使用 prefetch
提示符。