skip to content
月与羽

HTML 与 JS 加载顺序

/ 4 min read

1. 浏览器加载顺序基础

  • HTML 文件从上到下解析

    浏览器解析 HTML,遇到标签就处理,构建 DOM 树。

  • 遇到 **<script>** 标签时默认行为

    默认情况下,浏览器遇到 <script> 标签会暂停 HTML 解析,去加载并执行该 JS 脚本,执行完成后继续解析 HTML。

  • 遇到 CSS 文件时,会先加载 CSS,构建 CSSOM,然后渲染页面


2. <script> 标签的几种常见写法及加载顺序影响

2.1 默认 <script src="..."></script>(无属性)

  • 浏览器遇到脚本标签时会阻塞 DOM 解析,先下载并执行脚本,执行完成后继续解析后面的 HTML。
  • 这会导致页面渲染变慢,尤其脚本较大时。

2.2 带 defer 属性的 <script defer src="..."></script>

  • 脚本会异步下载,但会延迟执行,直到 HTML 完全解析完毕后,才按顺序执行所有 defer 脚本。
  • 适合依赖 DOM 完全构建完毕的脚本。
  • 多个 defer 脚本执行顺序和它们在 HTML 中的出现顺序一致。

2.3 带 async 属性的 <script async src="..."></script>

  • 脚本异步下载,下载完成后立即执行,不保证执行顺序,且执行时会暂停 HTML 解析。
  • 适合不依赖 DOM 或其他脚本的独立脚本。
  • 多个 async 脚本的执行顺序是不确定的。

2.4 内联 <script> 标签(无 src

  • 浏览器解析到内联脚本时,立即执行,然后继续解析 HTML。

3. JS 与 HTML 文件的加载顺序常见场景

情况HTML 解析脚本下载脚本执行页面渲染备注
内联 <script>阻塞,立即执行无下载立即执行脚本执行后继续适合短脚本
<script src="..." >阻塞,暂停解析同步下载同步执行脚本执行后继续会阻塞页面,影响性能
<script defer src="...">不阻塞,继续解析异步下载HTML解析完成后按顺序执行脚本执行后渲染推荐加载顺序敏感的脚本
<script async src="...">不阻塞,继续解析异步下载下载完成立即执行脚本执行时会暂停HTML解析不保证执行顺序,适合独立脚本

4. 具体示例

<!DOCTYPE html>
<html>
<head>
<script src="a.js"></script> <!-- 解析到这里,暂停,下载a.js,执行a.js,继续 -->
<script src="b.js" defer></script> <!-- 下载b.js异步,执行延后 -->
<script src="c.js" async></script> <!-- 下载c.js异步,下载完成立即执行 -->
</head>
<body>
<h1>标题</h1>
<script>
console.log('内联脚本执行');
</script>
</body>
</html>

执行顺序可能是:

  • a.js(阻塞执行)
  • 内联脚本
  • c.js(async,随时执行)
  • b.js(defer,页面解析完后按顺序执行)

5. 建议实践

  • 放JS文件于页面底部 **<body>** 结束前,避免阻塞页面渲染。
  • 使用 **defer** 加载依赖 DOM 的脚本,保证执行顺序且不阻塞。
  • 使用 **async** 加载独立脚本,提高页面加载速度。
  • 内联小脚本适用于页面早期逻辑,如设置变量或小型初始化。