HTML结构决定JS执行与排版任务的阻塞关系;同步script阻塞HTML解析导致首屏白屏,defer脚本保序且不卡首屏,template绕开主线程争抢,嵌套div拉长样式继承链引发JS执行后积压布局计算。

HTML结构本身不能协调线程竞争,但能决定JS执行和排版任务谁先卡住谁、卡在哪一环、卡多久。
同步<script>放在<head>里为什么首屏白屏更久</script>
不是“<script>阻塞了渲染”,而是它让JS执行时机提前到了DOM构建最开始阶段。浏览器遇到同步<script>(无async或defer),会立刻暂停HTML解析器,把主线程控制权交给JS引擎。
- 此时
<body>甚至还没开始解析,document.body是null,DOM树几乎为空 - 哪怕页面只写了
<h1>Hello</h1>,它也进不了DOM树,更不会触发样式计算或绘制 - 用户看到的是“完全空白”,而不是“文字没样式”——因为连文本节点都没生成
用defer是唯一保序且不卡首屏的结构方案
defer脚本下载不阻塞HTML解析,执行被推迟到DOM解析完毕后、DOMContentLoaded事件触发前。这是HTML结构层唯一能兼顾执行顺序与首屏性能的原生机制。
- 多个
defer脚本按文档顺序执行,不打乱依赖关系 - DOM已完整构建,脚本能安全访问
document.getElementById等API - 注意:
defer只对带src的外部脚本生效,内联脚本加defer会被忽略 - 如果脚本依赖CSSOM(比如要读
getComputedStyle),仍可能因CSS加载延迟而等待
<template>不是“懒加载”,是彻底绕开主线程争抢
<template>内容不参与HTML解析流程,也不触发JS执行、资源加载或样式计算。它只是内存中一个惰性的DocumentFragment,克隆插入时跳过了从字符串解析HTML的全部开销。
立即学习“前端免费学习笔记(深入)”;
- 直接
innerHTML = htmlStr:每次都要重新解析、构建节点、触发重排预备,JS执行期间无法做这事 - 克隆
template.content:只做内存复制,不触发布局/样式计算,JS执行完立刻可插入 - 注意:
template.content是DocumentFragment,不能直接querySelector,得先挂载或用querySelectorAll遍历 - 模板里的
<script>和<style>会被忽略,事件监听必须手动绑定
真正容易被忽略的点在于:嵌套过深的<div>会让样式继承链拉长,布局计算复杂度非线性上升;当JS正在执行时,这些积压的样式计算和布局任务会在JS结束后一口气补完——用户感知就是“点了按钮,界面卡顿半秒才响应”,而这和JS本身写得多差无关。



















