2009年12月24日星期四

Note on Non-Blocking Scripts Loading on Desktop Browsers

The presentation: http://stevesouders.com/docs/velocity-20090622.ppt

Now we have six ways to do loading Scripts without blocking, but not all work on all browsers, and not all work as we need.

XHR Eval

var xhrObj = getXHRObject();
xhrObj.onreadystatechange=function()
{
    if (xhrObj.readyState != 4) return;
    eval(xhrObj.responseText);
}

Script must have same domain as main page, and script must to be refactored.

XHR Injection

var xhrObj = getXHRObject();
xhrObj.onreadystatechange=function()
{
    if (xhrObj.readyState != 4) return;
    var se = document.createElement('script');
    document.getElementsByTagName('head')[0].appendChild(se);
    se.text = xhrObj.responseText;
}
xhrObj.open('GET', 'A.js', true);
xhrObj.send('');

Script must have same domain as main page.

Script in iFrame

Create a page contains the script, like A.html contains A.js, than modify your main page and add iframe like:

<iframe src="A.html" width="0" height="0" frameborder="0" id="frame1"></iframe>

But iframe must have same domain as main page, and your scripts in both main page and iframe have to refactor, though the functions in A.js exist in iframe, not main page:

// Access iframe from main page: call function createNewDiv()
window.frames<sup><a href="#fn0">0</a></sup>.createNewDiv();

// Access main page from iframe: add a div element to main page
parent.document.createElement('div');

Script DOM Element

var se document.createElement('script');
se.src = 'http://anydomain.com/A.js';
document.getElementsByTagName('head')[0].appendChild(se);
Script and main page domains can differ, and no need to refactor JavaScript.

Script Defer

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

In this trick script and main page domains can differ, no need refactor JavaScript. But only supported in IE, now landed in FF 3.1.

document.write Script Tag


document.write('<script type="text/javascript" src="A.js"></script>');

Parallel downloads for scripts, nothing else. But all document.writes must be in same script block, parallelization only works in IE.

We must ensure scripts ordered execution, cause some scripts have dependencies.

We must avoid scripts ordered execution, that make faster execution.

But when inline scripts dependencies on scripts file? Script DOM Element works only on FF and Opera. Five techniques cames:
  • Hardcoded callback in the end of script. Not very flexible, does’t work for 3rd party scripts.
  • Window onload event. Must use async technique that blocks onload event to ensure scripts loaded before onload event have been fired. Script in iframe does this across most browsers.
  • Timer. Not smart enough, load if interval too low, delay if too high.
  • Degrading script tags. From John Resig, but doesn’t work for 3rd party scripts.
  • Script onload event. That’s what we want.
Example for script onload:

var init = function ()
{
    // do something....
}
var se = document.createElement('script');
se.src = 'some.js';
se.onloadDone = false;
se.onload = function ()
{
    if (!se.onloadDone)
    {
        init();
    }
    se.onloadDone = true;
}
se.onreadystatechange = function ()
{
    if ('loaded' === se.readyState)
    {
        if (!se.onloadDone)
        {
            init();
        }
    }
}
document.getElementsByTagName('head')[0].appendChild(se);

What about multiple scripts that depend on each other, and inline code that depends on the scripts? We got two solutions: Managed XHR, DOM Element and Doc Write.

Managed XHR: base XHR Injection than maintains a queue additional, than inline code runs after all scripts in queue load finished. This solution works fine at all browsers, but all scripts must same domain as main page. See example in the presentation page 48 – 50.

DOM Element and Doc Write: this solution depends on browser. Use Script DOM Element for Firefox and Opera, document.write for IE. But no benefit for Safari and Chrome, they don’t load scripts in parallel, rely on Safari 4 and Chrome 2. When scripts same domain, order preserved, no blocking (on all browsers). If scripts on different domain, all browsers order preserved, all browsers load scripts in parallel except Safari 3 and Chrome 1, and load script and image in parallel only on Firefox, Safari 4 and Chrome 2.

best to move inline scripts above stylesheets or below other resources

Because browsers download stylesheets in parallel with other resources that follow unless the stylesheet is followed by an inline script.

Positioning inline scripts

  • Remember inline scripts carry a cost.
  • Avoid long-executing inline scripts.
  • Don’t put inline scripts between stylesheets and other resources.

标签: , ,

0 条评论:

发表评论

订阅 博文评论 [Atom]

<< 主页