Js预加载区分
慢才后生一、link标签
rel属性值preload
与prefetch
差异
1 | <link rel="preload" href="" as="script" /> |
注意: 特殊的 as 属性取值:
style 和 script 是最常用的两个值,因为它们分别对应预加载 CSS 和 JavaScript 文件。其他如 image、font 和 audio 也是在处理资源时比较常见的需求。
使用 as 属性时,除了指定合适的资源类型,还可以根据需要指定 type(如字体文件的 MIME 类型)以及 crossorigin(用于跨域请求时指定 CORS 策略)。
相同点:
- 只是利用多余带宽提前加载资源,但js不执行,图片、样式等也主动不引入;
- 不阻塞dom构建和css渲染,即在页面渲染的同时下载其它资源。
不同点:
- preload优先级高,一般用于当前页面重要资源的提前下载;
- 而prefetch优先级低,一般用于提前下载子页面等依赖的资源;
二、script标签
之defer
与async
属性 差异
1 | <script src="" defer ></script> |
没有defer
或async
下载
和执行
均会阻塞
HTML 解析,适合必须依赖 HTML 内容的脚本。
defer
不依赖于 DOM 解析完成后的操作,但需要在 DOM 完全加载之后执行的脚本。例如,初始化页面交互、绑定事件等;
与没有 defer 属性的普通
<script>标签
不同,带有 defer 属性的<script>标签
会延迟执行,但它仍会在页面解析过程中开始异步下载。也就是说,defer 属性让脚本的下载过程异步进行,但不会阻塞页面的其他内容(如 DOM 或其他资源)的加载。脚本执行顺序:所有带有 defer 属性的脚本会按照它们在文档中的出现顺序来执行,即使它们是异步下载的。也就是说,defer 保证了脚本按顺序执行,而不是基于下载完成的顺序;
多脚本
defer
,保证在html解析及下载依赖css完成后,在脚本依序执行阶段能缓解带宽压力(不过太多的defer在并行加载阶段,也会占用带宽;可结合脚本合并【合并请求】,代码压缩优化),利于首屏加载。执行时间:这些脚本会在页面解析完成后、DOMContentLoaded 事件触发之前执行。
举例
- 浏览器解析 HTML 文件,从上到下逐行解析。
- 遇到
<script defer="true" src="script.js"> 标签
时,浏览器会开始异步加载 script.js 文件。 - 同时,浏览器继续解析页面的其他 HTML 元素,解析 CSS 文件(如
<link rel="stylesheet" href="styles.css">
),并开始应用 CSS 样式。 - 当 HTML 文档解析完毕,defer 属性的脚本会按顺序执行,确保文档的 DOM 结构已经完整,但此时 CSS 渲染已经完成。
(脚本尝试强制触发浏览器对某些样式计算(如getComputedStyle
)时可能被延迟,或 JS 存在动态加载额外的 CSS 文件,最好以onload
监听为准) - 在
defer脚本
均执行完成后,DOMContentLoaded
事件会被触发。
async
- 从
script标签
位置开始下载:浏览器会在解析到 async 属性的<script>标签
时立即开始下载(下载过程
不阻塞 html解析)。 - 下载完成后执行:脚本会在下载完成后立即执行,执行顺序取决于各自下载的顺序,而不是在 HTML 中的顺序(
执行过程
占用主线程,会阻塞 html解析和依赖的css下载,优先执行完毕后才会继续解析html;太多async会抢占带宽,影响css等关键资源加载,有碍页面渲染)。 - 主要用于“广告”,“监视脚本”或其它第三方独立插件。
补充
<link rel="preload" href="" as="script">
能缩短加载其它页面的时间,但使用太多可能造成流量拥堵,不利于首屏加载。同时与<script src="" defer />
能提前下载关键资源在且dom完成后顺序执行,是个好实践。