JavaScript 文件加载与阻塞问题之性能优化案例详解

上来先给一个问题:在书写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 文件加载与阻塞问题内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 完美解决JS文件页面加载时的阻塞问题

    关于页面加载时的时间消费,许多书中都做出了介绍,也提出了很多种方法.本文章就详细介绍XHR注入. 概述:JS分拆的方法 1.XHR注入:就是用ajax异步请求同域包含脚本的文件,然后将返回的字符串转化为脚本使用,该方法不会造成页面渲染和onload事件的阻塞,因为是异步处理,推荐使用. 2.iframe注入:加载一个iframe框架,通过使用iframe框架中的脚本来避免src方式加载脚本的阻塞,但是iframe元素开销较大,不推荐. 3.DOM注入:就是创建script元素,通过制定该元素的s

  • 重写document.write实现无阻塞加载js广告(补充)

    无阻塞加载javascript,对于页面性能优化有很大的作用,这样能有效的减少js对页面加载的阻塞.特别是一些广告js文件,由于广告内容有可能是富媒体,更是很可能成为你页面加载提速的瓶颈,高性能javascript告诉我们,同学,提升你的网页速度,就无阻塞地加载JS吧. 于是便有一下代码出现. (function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.

  • 无阻塞加载js,防止因js加载不了影响页面显示的问题

    浏览器加载静态资源和js的方式都是线性加载,所以一般情况可以将js放到</body>前,防止UI线程的阻塞. 而某些时候我们既希望js在整个网页的头部就加载,又担心js阻塞导致网站加载缓慢,就可以用到无阻塞加载js技术. Dynamic Script Elements 动态脚本元素 DOM允许我们使用Javascript动态创建HTML的几乎所有文档内容,一个新的<script>元素可以非常容易的通过标准DOM创建: var script = document.createElem

  • JavaScript中的无阻塞加载性能优化方案

    Javascript在浏览器中的性能,可以说是前端开发者所要面对的最重要的可用性问题. 在Yahoo的Yslow23条规则当中,其中一条是将JS放在底部 .原因是,事实上,大多数浏览器使用单进程处理UI和更新Javascript运行等多个任务,而同一时间只能有一个任务被执行.Javascript运行了多长时间,那么在浏览器空闲下来响应用户交互之前的等待时间就有多长. 从基本层面说,这意味着<script>标签的出现使整个页面因脚本解析.运行而出现等待.不论实际的 JavaScript 代码是内

  • JavaScript无阻塞加载和defer、async详解

    无阻塞加载 把js放在head里,浏览器是怎么去执行它的呢,是按顺序加载还是并行加载呢?在旧的浏览器下,都是按照先后顺序来加载的,这就保证了加载的js依赖不会发生问题.但是少部分新的浏览器已经开始允许并行加载js了,也就是说可以同时下载js文件,但是还是按先后顺序执行文件的. 下载是异步的没问题,但是每个javascript执行的时候还是同步的,就是先出现的script标签一定是先执行,即使是并行下载它是最后一个下载完成的,除非标有defer的script标签.任何javascript在执行的时

  • JavaScript 文件加载与阻塞问题之性能优化案例详解

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

  • React 首页加载慢问题性能优化案例详解

    学习了一段时间React,想真实的实践一下.于是便把我的个人博客网站进行了重构.花了大概一周多时间,网站倒是重构的比较成功,但是一上线啊,那个访问速度啊,是真心慢,慢到自己都不能忍受,那么小一个网站,没几篇文章,慢成那样,不能接受.我不是一个追求完美的人,但这样可不行.后面大概花了一点时间进行性能的研究.才发现慢是有原因的. React这类框架? 目前主流的前端框架React.Vue.Angular都是采用客户端渲染(服务端渲染暂时不在本文的考虑范围内).这当然极大的减轻了服务器的压力.相对的浏

  • javascript文件加载管理简单实现方法

    本文实例讲述了javascript文件加载管理简单实现方法.分享给大家供大家参考.具体如下: 这里介绍超级简单的进行javascript的文件(模块)的加载管理, 实现sea.js或者require.js核心功能,用一行 <script src="js/light/light.js"></script> 加载所有的js文件. //按照lightJs的顺序,让网页加载js文件: var lightJs = [ "./js/light/pre/jquery

  • JavaScript es6中var、let以及const三者区别案例详解

    首先,一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系?         ECMAScript是一个国际通过的标准化脚本语言.JavaScript由ECMAScript和DOM.BOM三者组成.可以简单理解为:ECMAScript是JavaScript的语言规范,JavaScript是ECMAScript的实现和扩展.         2011 年,ECMAScript 5.1 版发布.之前我们大部分人用的也就是ES5         2015 年 6 月,ECM

  • Ajax 文件上传进度监听之upload.onprogress案例详解

    $.ajax实现 <!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-Compati

  • 学习javascript文件加载优化

    在js引擎部分,我们可以了解到,当渲染引擎解析到script标签时,会将控制权给JS引擎,如果script加载的是外部资源,则需要等待下载完后才能执行. 所以,在这里,我们可以对其进行很多优化工作. 放置在BODY底部 为了让渲染引擎能够及早的将DOM树给渲染出来,我们需要将script放在body的底部,让页面尽早脱离白屏的现象,即会提早触发DOMContentLoaded事件. 但是由于在IOS Safari, Android browser以及IOS webview里面即使你把js脚本放到

  • 微信小程序下拉加载和上拉刷新两种实现方法详解

    方法一:onPullDownRefresh和onReachBottom方法实现小程序下拉加载和上拉刷新 首先要在json文件里设置window属性 设置js里onPullDownRefresh和onReachBottom方法 下拉加载说明: 当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新. onPullDownRefresh(){ console.log('--------下拉刷新-------') wx.showNavigationBarLoadin

  • 使用javaScript动态加载Js文件和Css文件

    JS动态加载CSS 在可换主题的界面中具有很重要的意义,用户可以根据自己的浏览习惯选择自己喜欢的页面显示方式,下面详细说明. 希望下面的方法对你有帮助. (1)使用JavaScript动态加载Js文件 /*JavaScript动态加载Js文件*/ var scriptNode = document.createElement('script'); scriptNode.src = 'proxy.js?t='+new Date().getTime();/*附带时间参数,防止缓存*/ documen

  • 如何实现JavaScript动态加载CSS和JS文件

    项目中需要用到动态加载CSS 文件,整理了一下,顺便融合了动态加载JS 的功能写成了一个对象,先上代码: var dynamicLoading = { css: function(path){ if(!path || path.length === 0){ throw new Error('argument "path" is required !'); } var head = document.getElementsByTagName('head')[0]; var link =

  • JavaScript提高加载和执行效率的方法

    前言 无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成.JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长.浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或 JavaScript 的命名空间,它们对后面页面内容造成影响. 一个典型的例子就是在页面中使用document.write() . JavaScript 代码内嵌示例 <html> <head> <title>Sourc

随机推荐