You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Webpack构建生产资源时Deferred脚本仍被WebPageTest标记为渲染阻塞的原因排查

为什么带defer的Webpack分割脚本仍被WebPageTest标记为渲染阻塞?

嘿,这个问题我碰到过好几次了,咱们一步步拆解清楚:

先明确defer和async的核心差异

首先得把这两个属性的执行逻辑掰明白:

  • defer:脚本会并行下载,但会严格按照在HTML中的顺序执行,而且执行时机是DOM解析完成后、DOMContentLoaded事件触发之前。它不会阻塞DOM解析,但执行阶段会占用主线程。
  • async:脚本同样并行下载,但下载完成后会立即抢占主线程执行,不管DOM状态,也不管其他async脚本的顺序。

WebPageTest判定"渲染阻塞"的逻辑

WebPageTest标记渲染阻塞资源,看的不是脚本带不带defer/async,而是这个资源的处理(下载+执行)是否推迟了浏览器的首次绘制(First Paint)或首次内容绘制(First Contentful Paint)。它是基于实际主线程的阻塞情况来判定,而非单纯看脚本属性。

你的场景里defer出问题的原因

结合Webpack代码分割的情况,问题出在这几点:

  1. 执行时机刚好撞上首次渲染:Webpack分割后的chunk(比如vendor、common这类公共脚本)通常体积不小,下载完成的时间可能刚好在浏览器准备首次渲染的节点上。defer脚本会在DOM解析完立刻执行,这时候主线程被脚本执行占用,浏览器没法进行渲染操作,自然就被判定为阻塞了。
  2. 顺序执行放大了阻塞时间:defer是按顺序执行的,如果有多个分割后的chunk,前面的脚本执行耗时久,会直接阻塞后面所有defer脚本的执行,这段时间里主线程完全被占用,渲染只能一直等。

为什么换成async就解决了?

async的"下载完就执行"特性,反而帮你避开了首次渲染的关键节点:

  • 如果某个chunk下载完成时,浏览器已经完成了首次渲染,那它的执行就不会影响页面的初始绘制;
  • 就算下载完成得早,async脚本抢占主线程的时机也不一定卡在渲染的关键点上,而且各个async脚本独立执行,不会互相阻塞,总阻塞时间会更分散,不容易被WebPageTest判定为"渲染阻塞"。

额外提醒

不是说defer就一定会导致渲染阻塞,关键看脚本的执行时机和时长。如果你的分割chunk体积很小,或者下载完成时间晚于首次渲染,defer也不会被标记为阻塞。你可以在WebPageTest的瀑布流和主线程分析里,看看这些脚本的执行时间点和首次绘制的时间点是否重叠,就能更直观地确认问题啦。

内容的提问来源于stack exchange,提问作者Rabin Poudyal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:54:09