现代浏览器JS异步加载方案

好,不说废话,要凌晨了我快点写完,关于JS加载阻塞之类的不做科普,本文也不讨论IE9以下的浏览器。

headjs:“异步、并行加载并按你的顺序执行”,这个是最符合广大码农需求的,只是它越来越臃肿,连CSS Respone什么的都加进去了,没必要那么复杂

Loadjs:今天刚刚出现在OSC首页本人疯狂测试后发现,如果需要并行加载就是乱序的(哪个JS先下载完就先执行谁),如果要顺序下载就不能并发,经测试是下载一个执行一个,每个JS文件之间有10ms的空隙(JS下载和加载时所有渲染操作都要暂停,连下载都不行)

还有一个不说了,那是给No-Backend的网站专用的,很庞大一库,功能抄复杂

综上所述,如果你在乎性能和代码质量,一个都不要用

然而这些库都解决了一个致命问题——内联JS的异步加载,这就很纠结了对吧

然而,在现代浏览器环境下,很多原来性能障碍都解决了,新的障碍又特么出来了

1)所有现代浏览器(IE9+),都有“JS预加载器”其实本质是“预下载”,在渲染DOM的同时把所有网页资源都下载好(JS、css、img等等)

2)关于并行下载呢,经测试,所有浏览器都可以同时下载10-20个资源文件,比原来2-6个多的多了,作为现代的JS加载器没必要考虑并行下载的问题

3)现在大部分码农都只是不用或者只用JQuery里面的一部分了吧,追求性能是必须的,当然随着项目越来越庞大,引入Angular,Ember之类的巨型框架也是没办法,下载慢到不担心,关键执行慢卡死在那里结果用户一直白屏

4)defer="defer"已被所有浏览器支持,只是只适用于外部JS,内联JS只在IE有效,这正是本文要解决的问题

5)因为JS MVC框架的模板问题,很多JS代码不得不写在HTML里以获得服务器模板引擎的渲染(我还没看见过谁渲染一遍JS的,当然node除外哈。。)

好,show code

因为Riot.js,Angular.js这类框架对JS文件的加载时间段有很高的要求,所以用他们做demo再合适不过

1)给所有的外部JS加上 defer="defer"

    <script src=‘riot.min.js‘ defer=‘defer‘></script>
    <script src=‘todo.js‘ defer=‘defer‘></script>

2)给内联JS封装一个DOMContentLoaded,现代浏览器都提供了100%这个事件,然而并没有封装。。。。不像window.load那样直接可用,把下面的代码放入一个外部JS,并且不要使用 defer="defer"

  //保存domReady的事件队列
eventQueue = [];
 
//判断DOM是否加载完毕
isReady = false;
 
//判断DOMReady是否绑定
isBind = false;
 
/*执行domReady()
 *
 *@param    {function}
 *@execute  将事件处理程序压入事件队列,并绑定DOMContentLoaded
 *          如果DOM加载已经完成,则立即执行
 *@caller
 */
function domReady(fn){
    if (isReady) {
        fn.call(window);
    }
    else{
        eventQueue.push(fn);
    };
 
    bindReady();
};
 
/*domReady事件绑定
 *
 *@param    null
 *@execute  浏览器通过addEvListener绑定DOMContentLoaded,包括ie9+
 *@caller   domReady()
 */
function bindReady(){
    if (isReady) return;
    if (isBind) return;
    isBind = true;
        document.addEventListener(‘DOMContentLoaded‘,execFn,false);
};
 
/*执行事件队列
 *
 *@param    null
 *@execute  循环执行队列中的事件处理程序
 *@caller   bindReady()
 */
function execFn(){
    if (!isReady) {
        isReady = true;
        for (var i = 0; i < eventQueue.length; i++) {
            eventQueue[i].call(window);
        };
        eventQueue = [];
    };
};

如果非要支持IE6-8,那这里有个完整的demo http://dengo.org/archives/1037

亲测表示这个比Jquery的document.ready快!

其实这个时候JQuery的document.ready是用不了的,因为JQ还没被加载呢,除非你不对JQ异步加载,这样异步加载的意义就不大了

3)对于内联JS代码,以后统一用 domReady(function(){  //   });包裹

//内联JS 1
domReady(function(){
      riot.mount(‘todo‘, {
      title: ‘I want to behave!‘,
      items: [
        { title: ‘Avoid excessive coffeine‘, done: true },
        { title: ‘Hidden item‘, hidden: true },
        { title: ‘Be less provocative‘ },
        { title: ‘Be nice to people‘ }
      ]
    })
});

这个domReady()可以调用多次,直接用就行

好吧我科普一下,这个DOMContentLoaded就是在DOM结构加载完就触发(就是chrome developer tools -> TimeLine 里的那根蓝线),而window.load是在整个页面全部加载完时触发(就是chrome developer tools -> TimeLine 里的那根红线,在用户看来就是小菊花不转的时候)

好这样就解决了所有问题,结论就是,如果你需要引入很多庞大的库,又不想过于影响页面的首次加载速度(白屏时间),这个方案适合所有网站,嗯,用吧。

本文按cc-署名-以相同方式共享传播

时间: 2024-10-28 19:11:02

现代浏览器JS异步加载方案的相关文章

点评js异步加载的4种方式

主要介绍了点评js异步加载的4种方式,帮助大家更全面的了解js异步加载方式,感兴趣的小伙伴们可以参考一下 js异步加载的4种方式,点评开始. <!DOCTYPE html> <html> <head> <script src="http://common.cnblogs.com/script/jquery.js" type="text/javascript"></script> <script typ

页面优化——js异步加载

同步加载 在介绍js异步加载之前,我们先来看看什么是js同步加载.我们平时最常使用的就是这种同步加载形式: <script src="http://XXX.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像).渲染.代码执行.一般的script标签(不带async等属性)加载时会阻塞浏览器,也就是说,浏览器在下载或执行该js代码块时,后面的标签不会被解析,例如在he

JS异步加载的三种方式

js加载的缺点:加载工具方法没必要阻塞文档,过得js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作. 有些工具方法需要按需加载,用到再加载,不用不加载,. 默认正常模式下下,JS是同步加载的,即优先记载JS,只有当JS文件下载完,dom和css才开始加载,当某些事后我们需要JS异步加载,我们可以通过以下方式来设置异步加载,不同情况下选取不同方式即可 1.defer:defer JS异步下载,dom结构解析完(标签 + 样式(内容不一定下载完))才异步执行 仅I

一个小例子理解js异步加载

前几天笔试某公司有这样一道题.编写一个javascript函数,可以在页面上异步加载js,在加载结束后执行callback,并在IE和chrome下可以执行. 就这个题我写了一个DOM方法异步加载js的例子,可以给对于异步不了解的朋友参考感受一下. 众所周知,js是一种单线程的语言,它的Event Loop机制可以看一下阮一峰的这篇博客,讲解的很好 http://www.ruanyifeng.com/blog/2014/10/event-loop.html 下面看一下我写的例子 1 <!DOCT

JS异步加载的几种方式

一:同步加载 我们平时使用的最多的一种方式. <script src="http://yourdomain.com/script.js"></script> <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析,只有当当前加载完成,才能进行下一步操作.所以默认同步执行才是安全的.但这样如果js中有输

JS -- 异步加载进度条

今天在博客园问答里面看到博友问道怎么实现Ajax异步加载产生进度条. 很好奇就自己写了一个. 展现效果: 1) 当点击Load的时候,模拟执行异步加载. 浏览器被遮挡. 进度条出现. 实现思路: 1.当用户点击load button执行异步请求. 调用方法 出现加载条 2.怎么实现进度条呢? 1) 在document.body 新增一个div.覆盖浏览器. 设置背景会灰色. z-index = 999. 加载的时候让用户无法修改界面值 2) 在document.body 新增一个动态的div.

js异步加载

加载顺序是怎样的? 动态的和静态的都加载完之后才执行ready 还是只有静态的加载完之后就执行了? 页面加载完成之后是指什么才是完全加载完? 什么是并行,什么是异步 脚本的加载应该与文档的加载同时进行,并且不影响DOM的渲染. 文档加载?DOM加载 async属性是HTML5新增的.作用和defer类似,即允许在下载脚本的同时进行DOM的渲染.但是它将在下载后尽快执行(即JS引擎空闲了立马执行),不能保证脚本会按顺序执行.它们将在onload 事件之前完成. 异步加载的三种方式 http://w

Angular.js 与script.js 异步加载

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>angular.js</title> <script type="text/javascript" src="./js/script.js"></script> <!--<script type="text/ja

js异步加载 defer和async 比较

网上说法很多,很少一句话能总结清楚的,终于找到两句一针见血的描述,很到位: 相同点:都不阻塞DOM解析 defer  :顺序:保证先后顺序.解析:HTML 解析器遇到它们时,不阻塞(脚本将被异步下载),待文档解析完成之后,执行脚本. async  :顺序:不保证先后顺序.解析:HTML 解析器遇到它们时,不阻塞(脚本将被异步下载,一旦下载完成,立即执行它),并继续解析之后的文档. 总结一下:defer 效果是 :js异步下载完毕后且DOM解析完成后且DOMContentLoaded 事件触发之前