我有几个关于<script>标签的async和defer属性的问题,据我的理解,它只在HTML5浏览器中工作。
我的一个站点有两个外部JavaScript文件,目前位于</body>标记上方;第一个是来自谷歌的jquery,第二个是一个本地外部脚本。
在网站加载速度方面
在我在页面底部的两个脚本中添加async是否有任何优势?
在这两个脚本中添加async选项并将它们放在<head>的页面顶部是否有任何优势?
这是否意味着他们会在页面加载时下载?
我认为这会导致HTML4浏览器的延迟,但是它会加速HTML5浏览器的页面加载吗?
使用<script defer src=…
在<head>中加载带有属性的两个脚本是否与在</body>之前加载脚本具有相同的影响?
同样,我认为这会降低HTML4浏览器的速度。
使用<script async src=…
如果我有两个脚本异步启用
他们会同时下载吗?
还是一页一页地看?
脚本的顺序会成为问题吗?例如,一个脚本依赖于另一个脚本,所以如果一个脚本下载得更快,第二个脚本可能无法正确执行等等。
最后,在HTML5得到更广泛的应用之前,我是否应该保持现状?
如果您的脚本不包含DOM操作,而其他脚本不依赖于此,则Async是合适的。
例如:bootstrap cdn,jquery
如果您的脚本包含DOM操作,而其他脚本依赖于此,那么Defer是合适的。
例如:<script src= " createfirst.js " > //让这将创建元素<script src= " showfirst.js " > //在createfirst创建元素后,它将显示。
这样就可以:
例如:<script defer src= " createfirst.js " > //let this will create element <script defer src= " showfirst.js " > //在createfirst.js创建元素后,它将
这将按顺序执行脚本。
但如果我做出:
例如:<script async src= " createfirst.js " > //let this will create element <script defer src= " showfirst.js " > //在createfirst.js创建元素后,它将
然后,这段代码可能会产生意想不到的结果。
因为:如果html解析器访问createfirst脚本。它不会停止创建DOM,而是开始从src下载代码。一旦src被解析/代码被下载,它将立即与DOM并行执行。
如果showfirst.js比createfirst.js先执行,这可能是可能的,如果createfirst需要很长时间(假设在DOM解析结束后)。然后,showfirst将立即执行。
看起来defer和async的行为是依赖于浏览器的,至少是在执行阶段。说明“defer”仅适用于外部脚本。我假设async遵循相同的模式。
在IE 11及以下版本中,顺序是这样的:
异步(可以在页面加载时部分执行)
无(可以在页面加载时执行)
延迟(在页面加载后执行,所有延迟在文件中的位置顺序)
在Edge, Webkit等中,async属性似乎要么被忽略,要么被放在末尾:
data-page - speed-no-defer(在加载页面时,在任何其他脚本之前执行)
无(可以在页面加载时执行)
延迟(等待DOM加载,所有延迟在文件中的位置顺序)
async(似乎等待DOM加载)
在较新的浏览器中,data-pagespeed-no-defer属性在任何其他外部脚本之前运行。这适用于不依赖于DOM的脚本。
注意:当您需要明确外部脚本的执行顺序时,请使用defer。这告诉浏览器按照在文件中的位置顺序执行所有延迟脚本。
旁白:外部javascript的大小在加载时确实很重要……但对执行顺序没有影响。
如果您担心脚本的性能,那么您可能需要考虑缩小或使用XMLHttpRequest动态加载它们。
如果您的脚本不包含DOM操作,而其他脚本不依赖于此,则Async是合适的。
例如:bootstrap cdn,jquery
如果您的脚本包含DOM操作,而其他脚本依赖于此,那么Defer是合适的。
例如:<script src= " createfirst.js " > //让这将创建元素<script src= " showfirst.js " > //在createfirst创建元素后,它将显示。
这样就可以:
例如:<script defer src= " createfirst.js " > //let this will create element <script defer src= " showfirst.js " > //在createfirst.js创建元素后,它将
这将按顺序执行脚本。
但如果我做出:
例如:<script async src= " createfirst.js " > //let this will create element <script defer src= " showfirst.js " > //在createfirst.js创建元素后,它将
然后,这段代码可能会产生意想不到的结果。
因为:如果html解析器访问createfirst脚本。它不会停止创建DOM,而是开始从src下载代码。一旦src被解析/代码被下载,它将立即与DOM并行执行。
如果showfirst.js比createfirst.js先执行,这可能是可能的,如果createfirst需要很长时间(假设在DOM解析结束后)。然后,showfirst将立即执行。
渲染引擎经过几个步骤,直到它在屏幕上绘制任何东西。
它是这样的:
Converting HTML bytes to characters depending on encoding we set to the document;
Tokens are created according to characters. Tokens mean analyze characters and specify opening tangs and nested tags;
From tokens separated nodes are created. they are objects and according to information delivered from tokenization process, engine creates objects which includes all necessary information about each node;
after that DOM is created. DOM is tree data structure and represents whole hierarchy and information about relationship and specification of tags;
CSS也是同样的过程。CSS渲染引擎为CSS创建不同的/分离的数据结构,但它被称为CSSOM (CSS对象模型)
Browser只适用于对象模型,所以它需要知道所有关于DOM和CSSDOM的信息。
下一步是以某种方式组合DOM和CSSOM。因为没有CSSOM浏览器不知道在渲染过程中如何样式化每个元素。
以上所有信息意味着,你在html (javascript, css)浏览器中提供的任何东西都会暂停DOM构建过程。如果你熟悉事件循环,有一个简单的规则事件循环如何执行任务:
执行宏任务;
执行微任务;
呈现;
所以当你提供Javascript文件时,浏览器不知道JS代码要做什么,并停止所有的DOM构造过程,Javascript解释器开始解析和执行Javascript代码。
即使你在body标签的末尾提供Javascript,浏览器也会进行HTML和CSS的所有上述步骤,但渲染除外。它会找到Script标签并停止,直到JS完成。
但是HTML为脚本标记提供了两个额外的选项:async和defer。
Async -意思是当代码被下载时执行,并且在下载过程中不阻塞DOM构造。
延迟——意思是在代码下载和浏览器完成DOM构造和渲染过程后执行。
好的做法是将所有文件保存在源文件夹中,以便快速加载源文件。你需要下载所有的脚本,样式,图标和图像相关的文件,并把这些文件放入你的项目文件夹。
在项目中创建这些文件夹以保存不同的源文件,然后从这些文件夹中将所需的文件加载到页面中。
Js:保存脚本相关文件。
Css:保存与样式相关的文件。
Img:保存图像/图标相关文件
字体:保存字体相关文件
何时使用defer和async属性
defer属性:首先下载脚本文件,然后等待html解析。html解析结束后,脚本将执行。换句话说,它将保证在html解析之后执行所有脚本。
当脚本用于DOM操作时,Defer属性非常有用。意味着脚本将应用于文档html。
async属性:它将下载脚本文件并执行,而不等待html解析结束。换句话说,它不能保证在html解析之后执行所有脚本。
当脚本不用于DOM操作时,Async属性非常有用。有时,您只需要脚本进行服务器端操作或处理缓存或cookie,而不需要用于DOM操作。意味着脚本与所使用的html无关。
使用defer和async时的有用链接:
https://stackoverflow.com/a/68929270/7186739