上来先给一个问题:在书写html页面时,当你要从外部引入js文件时,script标签会放置在哪个位置呢,放置位置不同对页面加载有影响吗?
默认情况下,浏览器是同步加载 JavaScript 脚本:即渲染引擎遇到 script 标签就会停下来,等到执行完脚本,再继续向下渲染。如果是外部脚本,还必须加入脚本下载的时间。
如果脚本体积很大,下载和执行的时间就会很长,因此造成浏览器堵塞,用户会感觉到浏览器“卡死”,出现短暂的空白,没有任何响应。这会造成很不好的用户体验,解决这个问题有两种方案

①. 改变script标签的放置位置。最好将其丢在body标签的最后面,即放在</ body>标签的前面,这种方式不会影响浏览器的DOM渲染,会让页面处理执行完后才去执行它

②. 同步转异步。浏览器允许脚本异步加载,这种方式可以让 script 标签继续放在head头部,下面是两种异步加载的语法:

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

async与defer

异步就是 script 标签打开defer或async属性,脚本就会异步加载。浏览器渲染引擎遇到这一行命令,就会开始下载外部脚本,在下载的同时渲染引擎会直接执行后面的命令。

async和defer都会让外部脚本下载时,渲染引擎不停下来。

async属性与defer的区别就在于:

在这里插入图片描述

蓝色线代表网络读取(脚本下载),红色线代表执行,这俩都是针对脚本的;绿色线代表 HTML 解析。

defer属性,浏览器会立即下载相应的脚本,在下载的过程中页面的处理不会停止,等到文档解析完成后脚本才会执行

async属性,浏览器会立即下载相应的脚本,在下载的过程中页面的处理不会停止,下载完成后立即执行,执行过程中页面处理会停止。

若不设置任何属性,那么当与到script脚本时,会等script脚本下载和执行都完成之后才继续执行下面的页面处理。

】且async比defer更“厉害”,当同一标签同时使用两种属性时,遵循async!!!

多个脚本

async和defer的区别不仅体现在外部script文件的下载和执行上,更体现在多个脚本存在时的不同:
先来个代码示例:

外部script文件
1.js 文件:

// ... 非常多的js代码
console.log('1');

2.js 文件:

console.log('2');

主html文件

使用defer

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>js阻塞</title>
    <!-- defer会让dom先执行 -->
    <script src="./1.js" defer></script>
    <script src="./2.js" defer></script>
</head>
<body>
    <h1>js的阻塞是如何进行的?</h1>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            console.log('DOMContentLoaded');
        })
    </script>
</body>
</html>

控制台执行结果:

在这里插入图片描述

使用async

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>js阻塞</title>
    <!-- defer会让dom先执行 -->
    <script src="./1.js" async></script>
    <script src="./2.js" async></script>
</head>
<body>
    <h1>js的阻塞是如何进行的?</h1>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            console.log('DOMContentLoaded');
        })
    </script>
</body>
</html>

控制台执行结果:

在这里插入图片描述

从控制台的运行结果就可以看出:
defer第一个延迟脚本会先于第二个延迟脚本执行(当然,如果一些浏览器不完全遵照html5标准,也会出现不按顺序执行的情况),且这两个脚本会先于DOMContentLoaded事件执行。

async哪个先下载完成哪个就立即执行!!!这两个脚本不一定会在DOMContentLoaded事件触发之前执行,但一定会在window.onload 事件之前执行完成。另外,值得注意的是,在先下载完的脚本执行过程中,其他脚本不会停止下载,而会继续下载。

】DOMContentLoaded会在dom加载完成后触发,即文档完全加载和解析之后触发。
○ 更多关于DOMContentLoaded,请参考 https://www.jb51.net/article/222345.htm

小结

  1. 防堵塞的最佳实践就是将script标签放到body的最下面;
  2. defer 和 async 在网络读取(下载)方面是一样的,都是异步的(相较于 HTML 解析)
    它俩的差别在于脚本下载完之后何时执行,显然 defer 是最接近我们对于应用脚本加载和执行的要求的,尤其对于有script文件之间有依赖的情况(依赖就是可能这个js文件引用了上一个js文件的内容),它是按照加载顺序执行脚本的!!!
  3. async 则是一个乱序执行的主,对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行
    仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics
  4. defer/async都只适合与操作外部脚本,另外,在操作DOM脚本时最好不要使用async/defer,因为比如使用async时可能页面还没加载完,就执行了js代码,这样很可能产生异常;如果一定要使用,可以把需要操作 DOM 的js 部分放在 DOMContentLoaded 事件回调中执行☺!

参考

[1] https://blog.csdn.net/mx18519142864/article/details/82021754
[2] https://blog.csdn.net/weixin_42561383/article/details/86564715
[3] https://segmentfault.com/q/1010000000640869

到此这篇关于JavaScript 文件加载与阻塞问题之性能优化案例详解的文章就介绍到这了,更多相关JavaScript 文件加载与阻塞问题内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

JavaScript 文件加载与阻塞问题之性能优化案例详解的更多相关文章

  1. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. swift皮筋弹动发射飞机ios源码

    这是一个款采用swift实现的皮筋弹动发射飞机游戏源码,游戏源码比较详细,大家可以研究学习一下吧。

  4. Swift与Js通过WebView交互

    开发环境:Swfit2.3XCode8.2基础概念jscontext,jscontext是代表JS的执行环境,通过-evaluateScript:方法就可以执行一JS代码JSValue,JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等JSExport,JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用Swif

  5. JSCore swift

    如果双方相互引用,会造成循环引用,而导致内存泄露。以上是Jscore的基本使用,比较简单

  6. Swift WKWebView的js调用swift

    最近项目需求,需要用到JavaScriptCore和WebKit,但是网上的资源有限,而且比较杂,都是一个博客复制另外一个博客,都没有去实际敲代码验证,下面给大家分享一下我的学习过程。

  7. Swift WKWebView的swift调用js

    不多说,直接上代码:在html里面要添加的的代码,显示swift传过去的参数:这样就实现了swift给js传参数和调用!

  8. 在 Swift 專案中使用 Javascript:編寫一個將 Markdown 轉為 HTML 的編輯器

    你有強烈的好奇心,希望在你的iOS專案中使用JavaScript。jscontext中的所有值都是JSValue對象,JSValue類用於表示任意類型的JavaScript值。因此,我們既需要寫Swift代碼也要寫JavaScript代碼。此外,我們還會在JavaScript中按照這個類的定義來創建一個對象并對其屬性進行賦值。從Swift中呼叫JavaScript就如介紹中所言,JavaScriptCore中最主要的角色就是jscontext類。一個jscontext對象是位於JavaScript環境和本

  9. swift - WKWebView JS 交互

    本文介绍WKWebView怎么与js交互,至于怎么用WKWebView这里就不介绍了HTML代码APP调JS代码结果JS给APP传参数首先注册你需要监听的js方法名2.继承WKScriptMessageHandler并重写userContentController方法,在该方法里接收JS传来的参数3.结果

  10. swift 开发UIWebView跟JS的交互

    前言作为小白的我,才开始入门IOS,选择了swift来进行入门学习,学习做着公司一个简单的小小项目,该项目需要进行跟H5进行交互,然后我就开始研究了UIWebView的使用,其实基本原理跟Android的一样,因为我是Android开发的,所以就顺水推舟了。))//这里设置你需要加载的地址}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()//disposeofanyresourcesthatcanberecreate

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部