Possible to defer loading of jQuery?

JavascriptJqueryPagespeed

Javascript Problem Overview


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 some tabs which are placed low on the page (mostly out of initial view) and I'd like to defer jQuery until AFTER the page has rendered.

Google's deferral code adds a

Javascript Solutions


Solution 1 - Javascript

Try this, which is something I edited a while ago from the jQuerify bookmarklet. I use it frequently to load jQuery and execute stuff after it's loaded. You can of course replace the url there with your own url to your customized jquery.

(function() {
      function getScript(url,success){
        var script=document.createElement('script');
        script.src=url;
        var head=document.getElementsByTagName('head')[0],
            done=false;
        script.onload=script.onreadystatechange = function(){
          if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
            done=true;
            success();
            script.onload = script.onreadystatechange = null;
            head.removeChild(script);
          }
        };
        head.appendChild(script);
      }
    	getScript('http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js',function(){
    		// YOUR CODE GOES HERE AND IS EXECUTED AFTER JQUERY LOADS
    	});
    })();

I would really combine jQuery and jQuery-UI into one file and use a url to it. If you REALLY wanted to load them separately, just chain the getScripts:

getScript('http://myurltojquery.js',function(){
        getScript('http://myurltojqueryUI.js',function(){
              //your tab code here
        })
});

Solution 2 - Javascript

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"]);

Solution 3 - Javascript

Here is a good description of https://stackoverflow.com/a/24070373/548473">modern approach for async/defer javascript loading. But it doesn't works for inline scripts

<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" defer>
    $(function () {   //  <- jquery is not yet initialized
      ...
    });
</script>

The simplest solution for async loading was suggested by @nilskp - externalize script:

<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" src="resources/js/onload.js" defer></script>

Solution 4 - Javascript

I add this piece of code after the async/defered jquery script tag, this defines a temporary function $ that will accumulate whatever it is that needs to run when everything is done loading, and then once we're done use $ that by this time would be overwritten to execute the functions. With this piece of code there's no need to change the jQuery onload syntax further down in the document.

<script defer async src="https://code.jquery.com/jquery-2.2.0.min.js">
<script>
    var executeLater = [];
    function $(func) {
        executeLater.push(func);
    }
    window.addEventListener('load', function () {
        $(function () {
            for (var c = 0; c < executeLater.length; c++) {
                executeLater[c]();
            }
        });
    })
</script>

....and then...

<script>
    $(function() {
        alert("loaded");
    });
</script>

Solution 5 - Javascript

element.addEventListener("load", function () {
    $('#tabs').tabs()
}, false);

Try that.

Solution 6 - Javascript

Put jQuery and your jQuery dependent code at the end of your HTML file.

Edit: A little more clear

<html>
<head></head>
<body>
    <!-- Your normal content here -->
    <script type="text/javascript" src="http://path/to/jquery/jquery.min.js"></script>
    <script>//Put your jQuery code here</script>
</body>
</html>

Solution 7 - Javascript

In certain situation you could fire an event when jquery is loaded.

<script type="text/javascript">
	(function (window) {
		
		window.jQueryHasLoaded = false;

		document.body.addEventListener('jqueryloaded', function (e) {
			console.log('jqueryloaded ' + new Date() );
		}, false);

		function appendScript(script) {
			var tagS = document.createElement("script"), 
				s = document.getElementsByTagName("script")[0];
			tagS.src = script.src;
			s.parentNode.insertBefore(tagS, s);

			if ( script.id == 'jquery' ) {
				tagS.addEventListener('load', function (e) {
					window.jQueryHasLoaded = true;
					var jQueryLoaded = new Event('jqueryloaded');
					document.body.dispatchEvent(jQueryLoaded);
				}, false);
			}
		}

		var scripts = [
			{
				'id': 'jquery',
				'src': 'js/libs/jquery/jquery-2.0.3.min.js'
			},
			{
				'src': 'js/myscript1.js'
			},
			{
				'src': 'js/myscript2.js'
			}
		];

		for (var i=0; i < scripts.length; i++) {
			appendScript(scripts[i]);
		}

	}(window));
</script>

Then wrap your dependencies in a function:

// myscript1.js 
(function(){ 
	
	function initMyjQueryDependency() {
		console.log('my code is executed after jquery is loaded!');
		// here my code that depends on jquery
	}

	if ( jQueryHasLoaded === true )
		initMyjQueryDependency();
	else
		document.body.addEventListener('jqueryloaded', initMyjQueryDependency, false);

}());

If jquery finishes to load after the other scripts, your dependencies will be executed when the jqueryloaded event is fired.

If jquery is already loaded, jQueryHasLoaded === true, your dependency will be executed initMyjQueryDependency().

Solution 8 - Javascript

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

Solution 9 - Javascript

Well it seems to me, all you have to do is either a) add the jQuery code you want to run on load, to the end of the jQuery file or b) append it to the downloadJSAtOnload function like so:

<script type="text/javascript">

 // Add a script element as a child of the body
 function downloadJSAtOnload() {
 var element = document.createElement("script");
 element.src = "deferredfunctions.js";
 document.body.appendChild(element);
 $("#tabs").tabs(); // <==== NOTE THIS. This should theoretically run after the
                    // script has been appended, though you'll have to test this
                    // because I don't know if the JavaScript above will wait for
                    // the script to load before continuing
 }

 // Check for browser support of event handling capability
 if (window.addEventListener)
 window.addEventListener("load", downloadJSAtOnload, false);
 else if (window.attachEvent)
 window.attachEvent("onload", downloadJSAtOnload);
 else window.onload = downloadJSAtOnload;

</script>

Solution 10 - Javascript

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;

Solution 11 - Javascript

<!doctype html>
<html>
    <head>

    </head>
    <body>
        <p>If you click on the "Hide" button, I will disappear.</p>
        <button id="hide" >Hide</button>
        <button id="show" >Show</button>

        <script type="text/javascript">
            function loadScript(url, callback) {

                var script = document.createElement("script")
                script.type = "text/javascript";

                if (script.readyState) {  //IE
                    script.onreadystatechange = function() {
                        if (script.readyState == "loaded" ||
                                script.readyState == "complete") {
                            script.onreadystatechange = null;
                            callback();
                        }
                    };
                } else {  //Others
                    script.onload = function() {
                        callback();
                    };
                }

                script.src = url;
                document.body.appendChild(script);
            }
            loadScript("http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js",
                    function() {
                        //YAHOO.namespace("mystuff");
                        $("#show").click(function() {
                            $("p").show();
                        });
                        $("#hide").click(function() {
                            $("p").hide();
                        });

                        //more...
                    });
        </script>

    </body>
</html>

Solution 12 - Javascript

I think Modernizr.load() is worth a mention here - it handles dependency loading very nicely

Solution 13 - Javascript

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();
})

Solution 14 - Javascript

Appears that you just need <script defer> : http://www.w3schools.com/tags/att_script_defer.asp

Solution 15 - Javascript

Take a look jQuery.holdReady()

"Holds or releases the execution of jQuery's ready event." (jQuery 1.6+)

http://api.jquery.com/jQuery.holdReady/

Solution 16 - Javascript

I wanted to defer load jQuery on a WordPress site, so I couldn't practically update all the references using it. Instead wrote a small wrapper to queue the jQuery calls and call then whenever it's finally loaded. Stick it in the head, only 250 bytes or so, and it means jQuery can be deferred or async loaded without altering all the existing references. Made my load times much nicer.

My quick code may not work for all jQuery functions, but so far has worked with everything but one function call that I've tried. Normally I'm doing such custom stuff I don't make it available, but I thought I'd put this snippet online. Available here https://github.com/andrewtranter/jQuery_deferred_compat

Solution 17 - Javascript

Load all scripts at the end of html with http://labjs.com, it is 100% solution and I tested it many times against gtmetrix rules. example http://gtmetrix.com/reports/interactio.cz/jxomHSLV

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKevin P. RiceView Question on Stackoverflow
Solution 1 - JavascriptampersandView Answer on Stackoverflow
Solution 2 - JavascriptPevawiView Answer on Stackoverflow
Solution 3 - JavascriptGrigory KislinView Answer on Stackoverflow
Solution 4 - JavascriptasiopView Answer on Stackoverflow
Solution 5 - JavascriptMcKaylaView Answer on Stackoverflow
Solution 6 - JavascriptDanView Answer on Stackoverflow
Solution 7 - Javascriptmex23View Answer on Stackoverflow
Solution 8 - JavascriptJeremy BattleView Answer on Stackoverflow
Solution 9 - JavascriptRichard Marskell - DrackirView Answer on Stackoverflow
Solution 10 - JavascriptvalmarvView Answer on Stackoverflow
Solution 11 - JavascriptNanhe KumarView Answer on Stackoverflow
Solution 12 - JavascriptMikeView Answer on Stackoverflow
Solution 13 - JavascriptSeagullView Answer on Stackoverflow
Solution 14 - Javascriptc-smileView Answer on Stackoverflow
Solution 15 - JavascriptmikeycgtoView Answer on Stackoverflow
Solution 16 - JavascriptAnyView Answer on Stackoverflow
Solution 17 - JavascriptMirek KomárekView Answer on Stackoverflow