js 非阻塞加载

Non-onload-blocking async JS

June 28th, 2012. Tagged: JavaScript, performance

Update Oct 2013: for a more bulletproof version, tested in the wild, IE and all, check Philip's snippet at http://www.lognormal.com/blog/2012/12/12/the-script-loader-pattern/

Asynchronous JS is cool but it still blocks window.onload event (except in IE before 10). That's rarely a problem, because window.onload is increasingly less important, but still...

At my Velocity conference talk today Philip "Log Normal" Tellis asked if there was a way to load async JS without blocking onload. I said I don't know, which in retrospect was duh! because I spoke about Meebo's non-onload-blocking frames (without providing details) earlier in the talk.

Stage fright I guess.

Minutes later in a moment of clarity I figured Meebo's way should help. Unfortunately all Meebo docs are gone from their site, but we still have their Velocity talk from earlier years (PPT). There are missing pieces there but I was able to reconstruct a snippet that should load a JavaScript asynchronously without blocking onload.

Here it goes:

(function(url){variframe = document.createElement('iframe');
  (iframe.frameElement || iframe).style.cssText = "width: 0; height: 0; border: 0";
  varwhere = document.getElementsByTagName('script');
  where = where[where.length - 1];
  where.parentNode.insertBefore(iframe, where);
  vardoc = iframe.contentWindow.document;
  doc.open().write('<body οnlοad="'+
    'var js = document.createElement(\'script\');'+
    'js.src = \''+ url +'\';'+
    'document.body.appendChild(js);">');
  doc.close();
})('http://www.jspatterns.com/files/meebo/asyncjs1.php');

The demo page is right here. It loads a script (asyncjs1.php) that is intentionally delayed for 5 seconds.

Features

  • loads a javascript file asynchronously
  • doesn't block window.onload nor DOMContentLoaded
  • works in Safari, Chrome, Firefox, IE6789 *
  • works even when the script is hosted on a different domain (third party, CDN, etc), so no x-domain issues.
  • no loading indicators, the page looks done and whenever the script arrives, it arrives and does its thing silently in the background. Good boy!

* The script works fine in Opera too, but blocks onload. Opera is weird here. Even regular async scripts block DOMContentLoaded which is a shame.

Drawback

The script (asyncjs1.php) runs is in an iframe, so all document and window references point to the iframe, not the host page.

There's an easy solution for that without changing the whole script. Just wrap it in an immediate function and pass the document object the script expects:

(function(document){document.getElementById('r')... // all fine})(parent.document);

How does it work

  1. create an iframe without setting src to a new URL. This fires onload of the iframe immediately and the whole thing is completely out of the way
  2. style the iframe to make it invisible
  3. get the last script tag so far, which is the snippet itself. This is in order to glue the iframe to the snippet that includes it.
  4. insert the iframe into the page
  5. get a handle to the document object of the iframe
  6. write some HTML into that iframe document
  7. this HTML includes the desired script

转载于:https://www.cnblogs.com/freeDesignLife/p/3396009.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值