Possible to defer loading of jQuery?

前端 未结 16 974
孤街浪徒
孤街浪徒 2020-11-28 19:26

Let\'s face it, jQuery/jQuery-ui is a heavy download.

Google recommends deferred loading of JavaScript to speed up initial rendering. My page uses jQuery to set up s

相关标签:
16条回答
  • 2020-11-28 19:56

    There is a simple trick which Google Analytics uses.

    Preparation

    1. In the head of your HTML add a tiny script

    <script>
        window.jQuery_store = [];
        window.jQueryReady = function (fn) { jQuery_store.push(fn); }
    </script>
    

    The function jQueryReady will just save delegates into an array for future use.

    2. Create a new JS script jquery-ready.js with next content:

    // When jQuery is finaly ready
    $(function() {
        // Replace previous implementation
        window.jQueryReady = function(fn) {
            // jQuery is loaded call immediately
            fn();
        }
        
        // Call all saved callbacks
        for (var i = 0; i < window.jQuery_store.length; ++i) {
            try {
                window.jQuery_store[i]();
            } catch (err) {
                console.log(err);
            }
        }
    })
    

    When this script is loaded, it will:

    • Wait until jQuery is safe to use
    • Will replace the function jQueryReady with a new one, which just calls delegate immediately (the jQuery is ready at the given time).
    • Iterate through functions saved from previous jQueryReady calls.

    3. Put everything together Make jquery-ready.js load only after the jQuery is loaded. In your footer you will have:

    <script defer src=".../jquery.min.js">
    <script defer src=".../bootstrap.min.js">
    ... any other plugins for jQuery you probably need
    <script defer src=".../jquery-ready.js">
    

    This makes sure that the jquery-ready.js script will be executed only after the jQuery was executed.

    Usage

    You can now use jQueryReady function whenever you want.

    jQueryReady(function() {
        // jQuery is safe to use here
        $("div.to-be-hidden").hide();
    })
    
    0 讨论(0)
  • 2020-11-28 19:59

    Here's my version which supports chaining to be sure the scripts are loaded one after each other, based on ampersand's code:

    var deferredJSFiles = ['jquery/jquery', 'file1', 'file2', 'file3'];
    function downloadJSAtOnload() {
        if (!deferredJSFiles.length)
            return;
        var deferredJSFile = deferredJSFiles.shift();
        var element = document.createElement('script');
        element.src = deferredJSFile.indexOf('http') == 0 ? deferredJSFile : '/js/' + deferredJSFile + '.js';
        element.onload = element.onreadystatechange = function() {
            if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')
                downloadJSAtOnload();
        };
        document.body.appendChild(element);
    }
    if (window.addEventListener)
        window.addEventListener('load', downloadJSAtOnload, false);
    else if (window.attachEvent)
        window.attachEvent('onload', downloadJSAtOnload);
    else
        window.onload = downloadJSAtOnload;
    
    0 讨论(0)
  • 2020-11-28 20:00

    As this is a top ranking question on a important subject let me be so bold to provide my own take on this based on a previous answer from @valmarv and @amparsand.

    I'm using a multi-dimensional array to load the scripts. Grouping together those that have no dependencies between them:

    var dfLoadStatus = 0;
    var dfLoadFiles = [
          ["http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"],
          ["http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js",
           "/js/somespecial.js",
           "/js/feedback-widget.js#2312195",
           "/js/nohover.js"]
         ];
    
    function downloadJSAtOnload() {
        if (!dfLoadFiles.length) return;
    
        var dfGroup = dfLoadFiles.shift();
        dfLoadStatus = 0;
    
        for(var i = 0; i<dfGroup.length; i++) {
            dfLoadStatus++;
            var element = document.createElement('script');
            element.src = dfGroup[i];
            element.onload = element.onreadystatechange = function() {
            if ( ! this.readyState || 
                   this.readyState == 'complete') {
                dfLoadStatus--;
                if (dfLoadStatus==0) downloadJSAtOnload();
            }
        };
        document.body.appendChild(element);
      }
    
    }
    
    if (window.addEventListener)
        window.addEventListener("load", downloadJSAtOnload, false);
    else if (window.attachEvent)
        window.attachEvent("onload", downloadJSAtOnload);
    else window.onload = downloadJSAtOnload;
    

    It loads first jquery after it is loaded it continue to load the other scripts at once. You can add scripts easy by adding to the array anywhere on your page:

    dfLoadFiles.push(["/js/loadbeforeA.js"]);
    dfLoadFiles.push(["/js/javascriptA.js", "/js/javascriptB.js"]);
    dfLoadFiles.push(["/js/loadafterB.js"]);
    
    0 讨论(0)
  • 2020-11-28 20:03

    The following code should load your scripts after the window is finished loading:

    <html>
    <head>
        <script>
        var jQueryLoaded = false;
        function test() {
            var myScript = document.createElement('script');
            myScript.type = 'text/javascript';
            myScript.async = true;
            myScript.src = jQueryLoaded ? 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js' : 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js';
            document.body.appendChild(myScript);
    
            if(!jQueryLoaded){
                alert('jquery was loaded');
                jQueryLoaded = true;
                test();
            } else {
                alert('jqueryui was loaded');   
            }
        }
    
        if (window.addEventListener){
            alert('window.addEventListener');
            window.addEventListener("load", test, false);
        } else if (window.attachEvent){
            alert('window.attachEvent');
            window.attachEvent("onload", test);
        } else{
            alert('window.onload');
            window.onload = test;
        }
        </script>
    </head>
    <body>
    <p>Placeholder text goes here</p>
    </body>
    </html>
    

    Worked for me in Chrome, FF and IE9 - let me know if that helps

    0 讨论(0)
提交回复
热议问题