Files
skillhub-088-vercel-react-b…/rules/rendering-script-defer-async.md
2026-07-13 21:36:17 +08:00

70 lines
1.9 KiB
Markdown

---
title: 在 Script 标签上使用 defer 或 async
impact: HIGH
impactDescription: 消除渲染阻塞
tags: rendering, script, defer, async, performance
---
## 在 Script 标签上使用 defer 或 async
**影响程度:高(消除渲染阻塞)**
未使用 `defer``async` 的 Script 标签会在脚本下载和执行期间阻塞 HTML 解析。这会延迟首次内容绘制(First Contentful Paint)和可交互时间(Time to Interactive)。
- **`defer`**:并行下载,HTML 解析完成后执行,保持执行顺序
- **`async`**:并行下载,下载完成后立即执行,不保证执行顺序
对于依赖 DOM 或其他脚本的脚本,使用 `defer`。对于独立脚本(如分析工具),使用 `async`
**错误做法(阻塞渲染):**
```tsx
export default function Document() {
return (
<html>
<head>
<script src="https://example.com/analytics.js" />
<script src="/scripts/utils.js" />
</head>
<body>{/* content */}</body>
</html>
)
}
```
**正确做法(非阻塞):**
```tsx
export default function Document() {
return (
<html>
<head>
{/* Independent script - use async */}
<script src="https://example.com/analytics.js" async />
{/* DOM-dependent script - use defer */}
<script src="/scripts/utils.js" defer />
</head>
<body>{/* content */}</body>
</html>
)
}
```
**注意:** 在 Next.js 中,建议使用 `next/script` 组件配合 `strategy` 属性,而不是原生 script 标签:
```tsx
import Script from 'next/script'
export default function Page() {
return (
<>
<Script src="https://example.com/analytics.js" strategy="afterInteractive" />
<Script src="/scripts/utils.js" strategy="beforeInteractive" />
</>
)
}
```
参考文档:[MDN - Script 元素](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#defer)