blocking="render"不是标准HTML属性,浏览器完全忽略;真正控制脚本阻塞行为的只有async、defer和默认同步执行三种标准方式。

blocking="render" 是无效的 HTML 属性
浏览器完全不识别 blocking="render",加了也等于没加。这不是拼写错误,而是根本不存在的标准属性 —— HTML 规范里没有它,所有主流浏览器(Chrome、Firefox、Safari、Edge)都会直接忽略。你看到这个写法,大概率是把 async、defer 或者 media(用于 <link>)记混了,或是复制了某框架自定义的 data-blocking 类似字段。
真正影响脚本渲染阻塞的只有三个标准行为
决定一个 <script></script> 是否阻塞 HTML 解析和页面渲染,只看它有没有 async、defer,或者什么都没有(即默认同步模式):
-
async:脚本异步下载,下载完成立刻执行 —— 可能打断 DOM 解析,也可能在 DOM 构建中途执行;适合无依赖的埋点、统计类脚本 -
defer:脚本异步下载,但等到整个 HTML 解析完毕、DOM 构建完成后再按顺序执行;适合需要操作 DOM 且有依赖关系的初始化逻辑(如vendor.js必须在app.js之前) - 不加任何属性(默认):同步下载 + 同步执行 —— 遇到就暂停 HTML 解析,等它下载、编译、执行完才继续;这是最重的阻塞方式,首屏 JS 绝对要避免
常见误用和坑点
这些写法看着合理,实际会出问题:
-
<script async defer src="a.js"></script>:async和defer同时存在时,现代浏览器优先按async处理,defer被忽略 -
<script async>console.log('inline')</script>:async和defer只对外部脚本(带src的)有效,内联脚本加了也无效 - 把
<script src="app.js"></script>放在底部就以为“不阻塞”:它仍会阻塞 DOM 解析,只是此时 DOM 已基本建好,对用户感知影响变小,但不是零阻塞 - 在
里放 JS 且不加defer或async:会卡住整个 HTML 解析,FCP(首次内容绘制)时间直接拉长
想真正减少 JS 渲染阻塞?聚焦这几件事
别浪费时间调试虚构属性,优先检查真实链路:
立即学习“前端免费学习笔记(深入)”;
- 首屏关键 JS(比如路由初始化、核心 UI 渲染逻辑)必须用
defer,不能省 - 第三方脚本(GA、广告 SDK、客服组件)一律用
async,并确认它们不污染全局变量或依赖其他脚本 - 体积超过 100KB 的脚本(如图表库、富文本编辑器)考虑用
import()动态加载,配合await import('./chart.js') - 打开 Chrome DevTools 的 Network 面板,看
app.js请求是否长期处于Queueing状态 —— 这说明同域并发请求太多,得拆子域名或加<link rel="preconnect">
真正拖慢用户的是白屏时间和可交互时间,不是某个属性写没写对。只要 async、defer 用对位置,再配合资源预加载和代码分割,阻塞问题就解决了一大半。细节上最容易被忽略的是:CSSOM 未就绪时,JS 执行会被强制等待 —— 所以 CSS 加载顺序和粒度,其实和 JS 阻塞一样关键。



















