异步加载和延迟加载_通过延迟和异步有效加载JavaScript

  • Post author:
  • Post category:java


异步加载和延迟加载

When loading a script on an HTML page, you need to be careful not to harm the loading performance of the page.

在HTML页面上加载脚本时,需要注意不要损害页面的加载性能。

A script is traditionally included in the page in this way:

传统上,脚本是通过以下方式包含在页面中的:

<script src="script.js"></script>

whenever the HTML parser finds this line, a request will be made to fetch the script, and the script is executed.

只要HTML解析器发现这一行,就会请求获取脚本,并执行脚本。

Once this process is done, the parsing can resume, and the rest of the HTML can be analyzed.

完成此过程后,就可以继续进行解析,然后可以分析其余HTML。

As you can imagine, this operation can have a huge impact on the loading time of the page.

您可以想象,此操作可能会对页面的加载时间产生巨大影响。

If the script takes a little longer to load than expected, for example if the network is a bit slow or if you’re on a mobile device and the connection is a bit sloppy, the visitor will likely see a blank page until the script is loaded and executed.

如果脚本的加载时间比预期的要长一点,例如,如果网络有点慢,或者您使用的是移动设备,并且连接有点草率,那么访问者可能会看到空白页,直到脚本被加载为止。加载并执行。

位置很重要

(

The position matters

)

When you first learn HTML, you’re told script tags live in the

<head>

tag:

初学HTML时,系统会告诉您脚本标记位于

<head>

标记中:

<html>
  <head>
    <title>Title</title>
    <script src="script.js"></script>
  </head>
  <body>
    ...
  </body>
</html>

As I told you earlier, when the parser finds this line, it goes to fetch the script and executes it.

Then

, after it’s done with this task, it goes on to parse the body.

正如我之前告诉您的那样,当解析器找到这一行时,它将去获取脚本并执行它。

然后

,完成此任务后,它将继续解析正文。

This is bad because there is a lot of delay introduced. A very common solution to this issue is to put the

script

tag at the bottom of the page, just before the closing

</body>

tag.

这很糟糕,因为引入了很多延迟。 解决此问题的一种非常常见的方法是将

script

标记放在页面底部,紧接

</body>

标记之前。

In doing so, the script is loaded and executed after all the page is already parsed and loaded, which is a

huge improvement

over the

head

alternative.

这样,在所有页面都已经解析并加载之后,脚本便被加载并执行,这是

head

方法的

巨大改进

This is the best thing you can do if you need to support older browsers that do not support two relatively recent features of HTML:

async

and

defer

.

如果需要支持不支持HTML的两个相对较新的功能的较旧的浏览器,这就是最好的选择:

async



defer

异步和延迟

(

Async and Defer

)

Both async and defer are boolean attributes. Their usage is similar:

异步和延迟都是布尔属性。 它们的用法类似:

<script async src="script.js"></script>

<script defer src="script.js"></script>

if you specify both,

async

takes precedence on modern browsers, while older browsers that support

defer

but not

async

will fallback to

defer

.

如果同时指定两者,则

async

在现代浏览器中优先,而支持

defer

但不支持

async

旧版浏览器将回退到

defer

For the support table, check caniuse.com for async

https://caniuse.com/#feat=script-async

and for defer

https://caniuse.com/#feat=script-defer

对于支持表,请检查caniuse.com以获取异步

https://caniuse.com/#feat=script-async

和推迟

https://caniuse.com/#feat=script-defer

These attributes only make sense when using the script in the

head

portion of the page, and they are useless if you put the script in the

body

footer like we saw above.

这些属性仅在页面

head

使用脚本时才有意义,如果将脚本放在如上所示的

body

页脚中,它们将无用。

性能比较

(

Performance comparison

)

头部无延迟或异步

(

No defer or async, in the head

)

Here’s how a page loads a script without either defer or async, put in the

head

portion of the page:

这是页面加载到页面

head

不延迟或异步的脚本的方式:

Without defer or async, in the head

The parsing is paused until the script is fetched, and executed. Once this is done, parsing resumes.

暂停解析,直到提取并执行脚本。 完成此操作后,将继续解析。

体内没有延迟或异步

(

No defer or async, in the body

)

Here’s how a page loads a script without defer or async, put at the end of the

body

tag, just before it closes:

以下是页面加载时没有延迟或异步的脚本的方式,该脚本放置在

body

标签的末尾,即关闭之前:

Without defer or async, in the body end

The parsing is done without any pauses, and when it finishes, the script is fetched, and executed. Parsing is done before the script is even downloaded, so the page appears to the user way before the previous example.

解析过程没有任何暂停,完成后,将提取并执行脚本。 解析是在脚本下载完成之前完成的,因此该页面以用户的方式出现在上一个示例之前。

与异步,在头上

(

With async, in the head

)

Here’s how a page loads a script with

async

, put in the

head

tag:

这是页面如何使用

head

标签放置带有

async

的脚本的方式:

With async

The script is fetched asynchronously, and when it’s ready the HTML parsing is paused to execute the script, then it’s resumed.

脚本是异步获取的,准备就绪后,HTML解析将暂停以执行脚本,然后将其恢复。

推迟,在头上

(

With defer, in the head

)

Here’s how a page loads a script with

defer

, put in the

head

tag:

这是页面加载带有

head

标签的

defer

脚本的方式:

With defer

The script is fetched asynchronously, and it’s executed only after the HTML parsing is done.

该脚本是异步获取的,只有在HTML解析完成后才执行。

Parsing finishes just like when we put the script at the end of the

body

tag, but overall the script execution finishes well before, because the script has been downloaded in parallel with the HTML parsing.

解析完成时就像将脚本放在

body

标签的末尾一样,但是总体而言脚本执行早于完成,因为脚本是与HTML解析并行下载的。

So this is the winning solution in terms of speed 🏆

所以这是速度方面的制胜法宝

阻止解析

(

Blocking parsing

)


async

blocks the parsing of the page while

defer

does not.


async

阻止页面解析,而

defer

不阻止。

阻止渲染

(

Blocking rendering

)

Neither

async

nor

defer

guarantee anything on blocking rendering. This is up to you and your script (for example, making sure your scripts run after the

onLoad

) event.


async



defer

都不保证阻止渲染。 这取决于您和您的脚本(例如,确保脚本在

onLoad

之后运行)事件。

dom互动

(

domInteractive

)

Scripts marked

defer

are executed right after the

domInteractive

event, which happens after the HTML is loaded, parsed and the

DOM

is built.

标记为

defer

脚本在

domInteractive

事件后

domInteractive

执行,该事件在HTML加载,解析并构建

DOM

之后发生。

CSS and images at this point are still to be parsed and loaded.

此时CSS和图像仍然需要解析和加载。

Once this is done, the browser will emit the

domComplete

event, and then

onLoad

.

完成此操作后,浏览器将发出

domComplete

事件,然后发出

onLoad


domInteractive

is important because its timing is recognized as a measure of perceived loading speed.

See the MDN

for more.


domInteractive

非常重要,因为它的时间被认为是感知加载速度的度量。

有关

更多信息,

请参见MDN

保持秩序

(

Keeping things in order

)

Another case pro

defer

: scripts marked

async

are executed in casual order, when they become available. Scripts marked

defer

are executed (after parsing completes) in the order which they are defined in the markup.

另一个

defer

情况:标记为

async

脚本在可用时以随意顺序执行。 标记为

defer

脚本(在解析完成之后)将按照标记中定义的顺序执行。

告诉我最好的方法

(

Just tell me the best way

)

The best thing to do to speed up your page loading when using scripts is to put them in the

head

, and add a

defer

attribute to your

script

tag:

使用脚本时,加快页面加载速度的最佳方法是将它们放在

head

,并在

script

标签中添加

defer

属性:

<script defer src="script.js"></script>

This is the scenario that triggers the faster

domInteractive

event.

这是触发更快的

domInteractive

事件的方案。

Considering the pros of

defer

, is seems a better choice over

async

in a variety of scenarios.

在各种情况下,考虑

defer

的优点似乎是优于

async

的更好选择。

Unless you are fine with delaying the first render of the page, make sure that when the page is parsed the JavaScript you want is already executed.

除非可以延迟页面的第一次渲染,否则请确保在解析页面时,所需JavaScript已经执行。

翻译自:

https://flaviocopes.com/javascript-async-defer/

异步加载和延迟加载