基于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 相关文章推荐
JQuery 学习笔记 选择器之五
Jul 23 Javascript
javascript 特性检测并非浏览器检测
Jan 15 Javascript
JQuery扩展插件Validate 1 基本使用方法并打包下载
Sep 05 Javascript
js中Math之random,round,ceil,floor的用法总结
Dec 26 Javascript
七夕情人节丘比特射箭小游戏
Aug 20 Javascript
跟我学习javascript的函数和函数表达式
Nov 16 Javascript
JS判断两个对象内容是否相等的方法示例
Apr 10 Javascript
JavaScript实现的DOM绘制柱状图效果示例
Aug 08 Javascript
Vue.js中该如何自己维护路由跳转记录
May 19 Javascript
整理 node-sass 安装失败的原因及解决办法(小结)
Feb 19 Javascript
利用Vue的v-for和v-bind实现列表颜色切换
Jul 17 Javascript
原生js实现表格翻页和跳转
Sep 29 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
php实现大文件断点续传下载实例代码
2019/10/01 PHP
深入分析PHP设计模式
2020/06/15 PHP
Javascript 跨域访问解决方案
2009/02/14 Javascript
iframe如何动态创建及释放其所占内存
2014/09/03 Javascript
JS实现清除指定cookies的方法
2014/09/20 Javascript
js实现带缓冲效果的仿QQ面板折叠菜单代码
2015/09/06 Javascript
javascript函数自动执行常用方法汇总
2016/03/28 Javascript
jQuery表单验证插件解析(推荐)
2016/07/21 Javascript
浅谈bootstrap使用中的一些问题以及解决过程
2016/10/18 Javascript
谈谈因Vue.js引发关于getter和setter的思考
2016/12/02 Javascript
jQuery设置和获取select、checkbox、radio的选中值方法
2017/01/01 Javascript
Vue原理剖析 实现双向绑定MVVM
2017/05/03 Javascript
在vue项目中,使用axios跨域处理
2018/03/07 Javascript
Vue 路由 过渡动效 数据获取方法
2018/07/31 Javascript
在 Angular6 中使用 HTTP 请求服务端数据的步骤详解
2018/08/06 Javascript
vue项目中使用Svg的方法
2018/10/24 Javascript
Vue.Draggable拖拽功能的配置使用方法
2020/07/29 Javascript
node.js使用stream模块实现自定义流示例
2020/02/13 Javascript
如何在vue中使用jointjs过程解析
2020/05/29 Javascript
vue使用swiper实现左右滑动切换图片
2020/10/16 Javascript
vue中使用router全局守卫实现页面拦截的示例
2020/10/23 Javascript
js实现详情页放大镜效果
2020/10/28 Javascript
[02:48]DOTA2英雄基础教程 拉席克
2013/12/12 DOTA
Python常用的日期时间处理方法示例
2015/02/08 Python
Python中常用的8种字符串操作方法
2019/05/06 Python
Django model select的多种用法详解
2019/07/16 Python
python getpass实现密文实例详解
2019/09/24 Python
django实现模板中的字符串文字和自动转义
2020/03/31 Python
Spark处理数据排序问题如何避免OOM
2020/05/21 Python
在HTML5中使用MathML数学公式的简单讲解
2016/02/19 HTML / CSS
应届生服装设计自我评价
2013/09/20 职场文书
公司道歉信范文
2014/01/09 职场文书
小学阳光体育活动总结
2014/07/05 职场文书
人代会简报
2015/07/21 职场文书
大学生志愿者心得体会
2016/01/15 职场文书
Nginx服务器如何设置url链接
2021/03/31 Servers