“套”是性能隐形杀手,因dom构建耗时线性上升、css选择器匹配成本指数级增长,嵌套超4层即引发首屏明显延迟;应优先用flex/grid替代冗余包裹,动态列表改用documentfragment批量挂载。

为什么 <div> 套 <code><div> 是性能隐形杀手
<p>浏览器解析 HTML 是深度优先遍历,每多一层嵌套,DOM 构建耗时就线性上升;更麻烦的是 CSS 选择器匹配成本会指数级增长——比如 <code>.wrapper .content .item p 要逐层回溯父节点,实测嵌套超 4 层后,首屏渲染延迟明显可感。
- 用开发者工具 Elements 面板按
Ctrl+Shift+C 定位深层节点,重点查连续出现的 <div><div><div>
<li>能用 <code>display: grid 或 display: flex 实现的布局,直接干掉 2–3 层包裹容器
- 动态列表插入时,别循环
appendChild,改用 DocumentFragment 批量挂载,避免反复触发重排
<script></script> 放 还是 ?关键看有没有 defer
没加 defer 或 async 的外部脚本,放哪都阻塞解析:放在 里,HTML 解析立刻停住,等 JS 下载执行完才继续;放 底部,虽不阻塞 DOM 构建,但可能卡住 CSSOM(尤其当 JS 里读取了 getComputedStyle)。
- 核心逻辑模块(如路由、状态初始化)用
<script src="app.js" defer></script>,保证顺序执行且不阻塞
- 统计、埋点、广告类脚本用
async,它们彼此无依赖,下载完立刻跑
- 绝对不要在
<link rel="stylesheet"> 之前放没加属性的 <script></script>,否则 CSS 加载会被强制串行化
@import 在 CSS 里比你想象中更慢
@import 不是语法糖,它是加载时序炸弹:浏览器必须先下载主 CSS 文件,再逐个发起被 import 的资源请求,完全无法并行。哪怕只写一行 @import "theme.css";,也会让整个样式表加载拖慢 300ms+。
- 把所有
@import 替换成独立的 <link rel="stylesheet"> 标签,让浏览器自主并发下载
- 手写 CSS 或老项目里容易漏查,用
grep -r "@import" src/ 快速扫一遍
- 真要条件加载(比如暗色主题),用 JS 动态创建
link 元素,而不是靠 @import 搞 hack
哪些 <link rel="preload"> 真有用,哪些纯属添乱
preload 不是“越早下越好”,它是给浏览器一个明确指令:“这个资源我马上就要”。用错反而挤占带宽,拖慢真正关键的资源。
- 只对
DOMContentLoaded 前必须就位的资源生效:首屏字体(记得加 crossorigin)、关键图片、核心 JS 模块
-
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin> —— 少了 crossorigin,字体大概率被 CORS 拦截
- 别给所有
<script></script> 加 preload:它不推迟执行,反而可能让 JS 提前下载却卡在执行队列里,白占带宽
语义标签和加载策略这些事,单独看都不难,但组合起来容易互相踩脚——比如用了 <main></main> 却忘了它只能出现一次,或者加了 defer 却把脚本放在了 里又被 CSS 卡住。真正卡人的,往往是这些交叉点。
Ctrl+Shift+C 定位深层节点,重点查连续出现的 <div><div><div>
<li>能用 <code>display: grid 或 display: flex 实现的布局,直接干掉 2–3 层包裹容器appendChild,改用 DocumentFragment 批量挂载,避免反复触发重排
<script></script> 放 还是 ?关键看有没有 defer
没加 defer 或 async 的外部脚本,放哪都阻塞解析:放在 里,HTML 解析立刻停住,等 JS 下载执行完才继续;放 底部,虽不阻塞 DOM 构建,但可能卡住 CSSOM(尤其当 JS 里读取了 getComputedStyle)。
- 核心逻辑模块(如路由、状态初始化)用
<script src="app.js" defer></script>,保证顺序执行且不阻塞 - 统计、埋点、广告类脚本用
async,它们彼此无依赖,下载完立刻跑 - 绝对不要在
<link rel="stylesheet">之前放没加属性的<script></script>,否则 CSS 加载会被强制串行化
@import 在 CSS 里比你想象中更慢
@import 不是语法糖,它是加载时序炸弹:浏览器必须先下载主 CSS 文件,再逐个发起被 import 的资源请求,完全无法并行。哪怕只写一行 @import "theme.css";,也会让整个样式表加载拖慢 300ms+。
- 把所有
@import替换成独立的<link rel="stylesheet">标签,让浏览器自主并发下载 - 手写 CSS 或老项目里容易漏查,用
grep -r "@import" src/快速扫一遍 - 真要条件加载(比如暗色主题),用 JS 动态创建
link元素,而不是靠@import搞 hack
哪些 <link rel="preload"> 真有用,哪些纯属添乱
preload 不是“越早下越好”,它是给浏览器一个明确指令:“这个资源我马上就要”。用错反而挤占带宽,拖慢真正关键的资源。
- 只对
DOMContentLoaded前必须就位的资源生效:首屏字体(记得加crossorigin)、关键图片、核心 JS 模块 -
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>—— 少了crossorigin,字体大概率被 CORS 拦截 - 别给所有
<script></script>加preload:它不推迟执行,反而可能让 JS 提前下载却卡在执行队列里,白占带宽
<main></main> 却忘了它只能出现一次,或者加了 defer 却把脚本放在了 里又被 CSS 卡住。真正卡人的,往往是这些交叉点。











