时光轴

script 标签加载顺序 (defer & async)

2021-12-24  本文已影响0人  侯工

script 拥有的属性

引入方式 JavaScript 的两种方式

内联形式

这种方式指的是在 html 文件中,添加一个<script></scritp>标签,然后将 JavaScript代码直接写在里面

外置形式

外置形式是将 JavaScript 代码写在外部的一个文件里面,在 html 文件中通过 <script> 标签的 src 属性引入

两种引入形式的比较

对于这两种方式,毫无疑问,外置形式明显好于内联形式,主要表现为以下方面:

<script> 标签加载顺序

如果要谈<script> 标签加载顺序问题,首先要谈的就是标签的位置,因为标签的位置对于JavaScript加载顺序来说有着很重要的影响。

标签位置

<script> 标签的位置有两种,一种是方式<head>元素里面,另外一种就是放在<body> 元素中页面内容的后面,下面将一一介绍这两种形式:

<script> 标签放在<head>元素里
<!DOCTYPE html>
<html>

<head>
  <title>Example HTML Page</title>
  <script type="text/javascript" src="example1.js"></script>
  <script type="text/javascript" src="example2.js"></script>
</head>

<body>
  <!-- 这里放内容 -->
</body>
</html>

这是一种比较传统的做法,目的就是把所有外部文件(包括 CSS 文件和 JavaScript 文件)的引用都放在相同的地方.可是,在文档的 <head> 元素中包含所有 JavaScript 文件,意味着必须等到全部 JavaScript 代码都被下载、解析和执行完成以后,才能开始呈现页面的内容(浏览器在遇到 <body> 标签时才开始呈现内容)。对于那些需要很多 JavaScript 代码的页面来说,这无疑会导致浏览器在呈现页面时出现明显的延迟,而延迟期间的浏览器窗口中将是一片空白。很明显,这种做法有着很明显的缺点,特别是针对于现在的移动端来说,如果超过 1s 还没有内容呈现的话将是一种很差的用户体验。为了避免这个问题,就有了下面这种加载方式。

<script> 标签放在<body> 元素中页面内容的后面
<!DOCTYPE html>
<html>

<head>
  <title>Example HTML Page</title>
</head>

<body>
  <!-- 这里放内容 -->
  <script type="text/javascript" src="example1.js"></script>
  <script type="text/javascript" src="example2.js"></script>
</body>

</html>

对于这种方式,在解析包含的 JavaScript 代码之前,页面的内容将完全呈现在浏览器中。而用户也会因为浏览器窗口显示空白页面的时间缩短而感到打开页面的速度加快了

延迟加载

<script>的每个属性设计来肯定都是有用的,下面我们就来说一说 defer 属性。
HTML 4.01 为<script> 标签定义了 'defer 属性。这个属性的用途是表明脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟到整个页面都解析完毕后再运行。因此,在 <script> 元素中设置defer 属性,相当于告诉浏览器立即下载,但延迟执行,比如:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>script 标签</title>
  <script defer="defer" type="text/javascript" src="./js/01.js"></script>
  <script defer="defer" type="text/javascript" src="./js/02.js"></script>
</head>

<body>
  <!-- content -->
  <script type="text/javascript" src="./js/03.js"></script>
</body>

</html>

在这个例子中,虽然我们把 <script> 元素放在了文档的 <head> 元素中,但其中包含的脚本将延迟到浏览器遇到 标签后再执行。HTML5 规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于 DOMContentLoaded 事件执行。在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在 DOMContentLoaded 事件触发前执行,因此最好只包含一个延迟脚本。

异步加载

说完了延迟加载,然后我们再说下异步加载,即使用 async属性。
HTML5 为 <script> 元素定义了 async 属性。这个属性与 defer 属性类似,都用于改变处理脚本的行为。同样与 defer 类似, async 只适用于外部脚本文件,并告诉浏览器立即下载文件,下载完成后立即执行。但与 defer不同的是,标记为 async 的脚本并不保证按照指定它们的先后顺序执行。例如:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>script 标签</title>
  <script async type="text/javascript" src="./js/01.js"></script>
  <script async type="text/javascript" src="./js/02.js"></script>
</head>

<body>
  <!-- content -->
</body>

</html>

在以上代码中,可能由于 01.js 下载时间比较长,由于两个 <script> 标签都是异步执行,互不干扰,因此 02.js 可能就会先于 01.js 执行。因此,确保两者之间互不依赖非常重要。指定 async 属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容。为此,建议异步脚本不要在加载期间修改 DOM。

小结

上一篇下一篇

猜你喜欢

热点阅读