基于js文件加载优化(详解)


Posted in Javascript onJanuary 03, 2018

在js引擎部分,我们可以了解到,当渲染引擎解析到script标签时,会将控制权给JS引擎,如果script加载的是外部资源,则需要等待下载完后才能执行。 所以,在这里,我们可以对其进行很多优化工作。

放置在BODY底部

为了让渲染引擎能够及早的将DOM树给渲染出来,我们需要将script放在body的底部,让页面尽早脱离白屏的现象,即会提早触发DOMContentLoaded事件. 但是由于在IOS Safari, Android browser以及IOS webview里面即使你把js脚本放到body尾部,结果还是一样。 所以这里需要另外的操作来对js文件加载进行优化.

DEFER加载

这是HTML4中定义的一个script属性,它用来表示的是,当渲染引擎遇到script的时候,如果script引用的是外部资源,则会暂时挂起,并进行加载。 渲染引擎继续解析下面的HTML文档,解析完时,则会执行script里面的脚本。

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

他的支持度是<=IE9的.

并且,他的执行顺序,是严格依赖的,即:

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

当页面解析完后,他便会开始按照顺序执行 outside1 和 outside2文件。

如果你在IE9以下使用defer的话,可能会遇到 它们两个不是顺序执行的,这里需要一个hack进行处理,即在两个中间加上一个空的script标签

<script src="outside1.js" defer></script>
<script></script> //hack
<script src="outside2.js" defer></script>

ASYNC加载

async是H5新定义的一个script 属性。 他是另外一种js的加载模式。

渲染引擎解析文件,如果遇到script(with async)

继续解析剩下的文件,同时并行加载script的外部资源

当script加载完成之后,则浏览器暂停解析文档,将权限交给JS引擎,指定加载的脚本。

执行完后,则恢复浏览器解析脚本

可以看出async也可以解决 阻塞加载 这个问题。不过,async执行的时候是异步执行,造成的是,执行文件的顺序不一致。即:

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

这时,谁先加载完,就先执行谁。所以,一般依赖文件就不应该使用async而应该使用defer.

defer的兼容性比较差,为IE9+,不过一般是在移动端使用,也就不存在这个problem了。

脚本异步

脚本异步是一些异步加载库(比如require)使用的基本加载原理. 直接上代码:

function asyncAdd(src){
  var script = document.createElement('script');
  script.src = src;
  document.head.appendChild(script);
}
//加载js文件
asyncAdd("test.js");

这时候,可以异步加载文件,不会造成阻塞的效果.

但是,这样加载的js文件是无序的,无法正常加载依赖文件。

这时候,我们需要对上述函数进行优化.

var asyncAdd = (function(){
  var head = document.head,
    script;
  return function(src){
    script = document.createElement('script');
    script.src= src;
    script.async=false;
    document.head.appendChild(script);
  }
})();
//加载文件
asyncAdd("first.js");
asyncAdd("second.js");
//或者简便一点
["first.js","second.js"].forEach((src)=>{async(src);});

但是,使用脚本一步加载的话,需要等待css文件加载完后,才开始进行加载,不能充分利用浏览器的并发加载优势。而使用静态文本加载async或者defer则不会出现这个问题。

使用脚本异步加载时,只能等待css加载完后才会加载

使用静态的async加载时,css和js会并发一起加载

关于这三种如何取舍,那就主要看leader给我们目标是什么,是兼容IE8,9还是手机端,还是桌面浏览器,或者两两组合。

但是对于单独使用某一个技能的场景,使用时需要注意一些tips。

js文件放置位置应该放置到body末尾

如果使用async的话,最后加上defer以求向下兼容

<script src="test.js" async defer></script> //如果两者都支持,async会默认覆盖掉defer
//如果只支持一个,则执行对应的即可

通常,我们使用的加载都是defer加载(因为很强的依赖关系).

以上这篇基于js文件加载优化(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
google 搜索框添加关键字实现代码
Apr 24 Javascript
如何让页面在打开时自动刷新一次让图片全部显示
Dec 17 Javascript
js获取单选框或复选框值及操作
Dec 18 Javascript
javascript 判断整数方法分享
Dec 16 Javascript
JS实现从顶部下拉显示的带动画QQ客服特效代码
Oct 24 Javascript
Javascript之Math对象详解
Jun 07 Javascript
详解Angular中$cacheFactory缓存的使用
Aug 19 Javascript
jQuery 选择器(61种)整理总结
Sep 26 Javascript
jQuery Layer弹出层传值到父页面的实现代码
Aug 17 jQuery
bootstrapTable+ajax加载数据 refresh更新数据
Aug 31 Javascript
javascript合并两个数组最简单的实现方法
Sep 14 Javascript
vue 里面的 $forceUpdate() 强制实例重新渲染操作
Sep 21 Javascript
jQuery 实现左右两侧菜单添加、移除功能
Jan 02 #jQuery
js 取消页面可以选中文字的功能方法
Jan 02 #Javascript
js阻止默认右键的下拉菜单方法
Jan 02 #Javascript
webpack实用小功能介绍
Jan 02 #Javascript
js最简单的双向绑定实例讲解
Jan 02 #Javascript
js 将canvas生成图片保存,或直接保存一张图片的实现方法
Jan 02 #Javascript
js原生方法被覆盖,从新赋值原生的方法
Jan 02 #Javascript
You might like
用Zend Encode编写开发PHP程序
2010/02/21 PHP
ThinkPHP3.1新特性之动态设置自动完成及自动验证示例代码
2014/06/23 PHP
php fread读取文件注意事项
2016/09/24 PHP
php与python实现的线程池多线程爬虫功能示例
2016/10/12 PHP
Discuz论坛密码与密保加密规则
2016/12/19 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
PHP正则匹配到2个字符串之间的内容方法
2018/12/24 PHP
PHP扩展mcrypt实现的AES加密功能示例
2019/01/29 PHP
php上传后台无法收到数据解决方法
2019/10/28 PHP
THREE.JS入门教程(4)创建粒子系统
2013/01/24 Javascript
基于dom编程中 动态创建与删除元素的使用
2013/04/17 Javascript
原生javascript实现简单的datagrid数据表格
2015/01/02 Javascript
JavaScript中的toString()和toLocaleString()方法的区别
2017/02/15 Javascript
Bootstrap的Carousel配合dropload.js实现移动端滑动切换图片
2017/03/10 Javascript
node安装--linux下的快速安装教程
2017/03/21 Javascript
js实现把时间戳转换为yyyy-MM-dd hh:mm 格式(es6语法)
2017/12/28 Javascript
微信小程序内拖动图片实现移动、放大、旋转的方法
2018/09/04 Javascript
基于elementUI使用v-model实现经纬度输入的vue组件
2019/05/12 Javascript
vue中filters 传入两个参数 / 使用两个filters的实现方法
2019/07/15 Javascript
[02:30]DOTA2英雄基础教程 暗影恶魔
2013/12/17 DOTA
浅谈Python中函数的参数传递
2016/06/21 Python
Python实现变量数值交换及判断数组是否含有某个元素的方法
2017/09/18 Python
python针对不定分隔符切割提取字符串的方法
2018/10/26 Python
使用python判断你是青少年还是老年人
2018/11/29 Python
详解Python3之数据指纹MD5校验与对比
2019/06/11 Python
Python生成器常见问题及解决方案
2020/03/21 Python
Python bisect模块原理及常见实例
2020/06/17 Python
草莓网中国:StrawberryNet中国
2020/08/17 全球购物
办公室文员工作自我评价
2013/12/01 职场文书
新浪微博实习心得体会
2014/01/27 职场文书
英文求职信写作小建议
2014/02/16 职场文书
工程建设实施方案
2014/03/14 职场文书
2014年财务部工作总结
2014/11/11 职场文书
高中美术教学反思
2016/02/17 职场文书
班干部竞选演讲稿(精选5篇)
2019/09/24 职场文书
关于MybatisPlus配置双数据库驱动连接数据库问题
2022/01/22 Java/Android