How to defer loading of JavaScript file? - javascript

I don't want to call the JavaScript functions at the startup. The reason is simple, it will reduce the initial download size and the page will be appear faster. To do that I used the following code inside head section..
<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);
}
// 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>
But it did not work...please help me

Usually, it's better to put scripts in the end of your body, and call them immediately.
Scripts block loading of the page, so putting them at the end of body allows the page to load quickly, and the javascript will load with page already ready.

document.head.appendChild(element)

You can use <script defer> (defer attribute on HTML script tag).
Example:
<script src="link/to/yourfile.js" defer></script>
defer will download the file during HTML parsing and will only execute it after the parser has completed. defer scripts are also guaranteed to execute in the order that they appear in the document.

Related

Efficient way to defer js

I intend to call a js, which will not use anything when loading the page. Therefore, I need to call this js only when the entire page has been loaded, so as not to delay anything or load the screen for the user.
<html>
<body>
<script type="text/javascript" defer=defer src="function.js"></script>
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "function.js";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
</body>
</html>
My question is: in the above ways, which one would be more efficient? I need to decrease the loading time of my page and with that I want to "postpone" everything that is not necessary.
The “defer” keyword postpones loading of scripts until the DOMContentLoaded event is fired.
From the Mozilla Developer Center:
The DOMContentLoaded event is fired when the document has been
completely loaded and parsed, without waiting for stylesheets, images,
and subframes to finish loading (the load event can be used to detect
a fully-loaded page).
This means that version 1 (defer) will possibly start loading the scripts earlier than version 2, while still keeping the loading efficient.

Dynamically generated script tag does not execute after it is appended to the head tag [duplicate]

I am trying to load a certain script after page load executes, something like this:
function downloadJSAtOnload(){
var element = document.createElement("script");
element.src = "scriptSrc";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
And while this script seems to execute and download 'scriptSrc', and append it right before the end of the body tag, it yields the following message (not an error) in the console (chrome)
Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.
What does this even mean? And am I supposed to do something differently? Even though I get the expected behavior?
An asynchronously loaded script is likely going to run AFTER the document has been fully parsed and closed. Thus, you can't use document.write() from such a script (well technically you can, but it won't do what you want).
You will need to replace any document.write() statements in that script with explicit DOM manipulations by creating the DOM elements and then inserting them into a particular parent with .appendChild() or .insertBefore() or setting .innerHTML or some mechanism for direct DOM manipulation like that.
For example, instead of this type of code in an inline script:
<div id="container">
<script>
document.write('<span style="color:red;">Hello</span>');
</script>
</div>
You would use this to replace the inline script above in a dynamically loaded script:
var container = document.getElementById("container");
var content = document.createElement("span");
content.style.color = "red";
content.innerHTML = "Hello";
container.appendChild(content);
Or, if there was no other content in the container that you needed to just append to, you could simply do this:
var container = document.getElementById("container");
container.innerHTML = '<span style="color:red;">Hello</span>';
A bit late to the party, but Krux has created a script for this, called Postscribe. We were able to use this to get past this issue.
In case this is useful to anyone I had this same issue. I was bringing in a footer into a web page via jQuery. Inside that footer were some Google scripts for ads and retargeting. I had to move those scripts from the footer and place them directly in the page and that eliminated the notice.
You can also call
document.open() before document.write()
call
document.close()
when you're done.
It may not be best practice for a real webpage but for testing etc.. can be used.

Does "onload()" of HTML conflicts with the delay of loading javascript?

The thing is, i'm adding Annotorious to my openSeadragon project.
http://annotorious.github.io/demos/openseadragon-preview.html
to get this plugins start, Following are the options.
<script>
function init() {
anno.makeAnnotatable(document.getElementById('myImage'));
}
</script>
...
<body onload="init();">
<img src="example.jpg" id="myImage" />
</body>
Here is the problem, i use these to delay the loading of javascript on the viewer block.
<script type="text/javascript">
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
Once i add onload="init();" to my code.the viewer won't function.
Are there conflicts between these two? if so, how to solve it?
I think this should help:
<script type="text/javascript">
var htmlOnLoad = window.onload;
window.onload = function(e){htmlOnLoad(e); downloadJSAtOnload(e)};
</script>
The idea is to keep the handler bound with HTML and call both: the html- and js- handlers.
Onload behavior is like so:
(probably depends on the browser type - behavior will might change - I worked on chrome)
If you set body onload="_fn" it will work on page loads
If you add window.onload=_fn on top of the page script (before the body tag) they will both load (2 then 1)
If you will add window.onload on the most bottom area of the HTML. It will be the only one to be executed on page load. (body "onload" will be override)
Adding an event listener to the window - you can add as much as you need and they will all be loaded as ordered respectively.
When the load event fires you are trying to do two things:
Call init (which, in turn, calls anno.makeAnnotatable)
Asynchronously load the JavaScript which makes anno.makeAnnotatable available
You can't call the function before it exists. You have to delay the calling of init until the loading of the JS that downloadJSAtOnload triggers has finished. (The specifics of that depend on how downloadJSAtOnload works).

Javascript Deferred Functions

I've been looking around at JavaScript to try and get some code to load asynchronously
I found this code sample
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "defer.js";
document.body.appendChild(element);
}
if (window.addEventListener) {
window.addEventListener("load", downloadJSAtOnload, false);
}
else if (window.attachEvent) {
window.attachEvent("onload", downloadJSAtOnload);
}
else {
window.onload = downloadJSAtOnload;
}
</script>
from http://www.feedthebot.com/pagespeed/defer-loading-javascript.html
The thing is it doesn't quite do what I'm trying to achieve. I would like to be able to do something similar but setup a deferred or some type of function that is called after this has all loaded. Is that possible? If so can anyone help explain how?
You can try to use the onload event of the script tags you are loading. See this question, for example: Trying to fire the onload event on script tag. However, this mechanism seems pretty sketchy and may not be cross-browser.
Another possible approach is to have the script that is being loaded trigger an event that can be handled by the existing javascript on the page. This may or may not make sense for your particular case, and it requires you to have control over the loaded script.
Finally, these days it's rare for javascript loading to be a performance bottleneck for your website. So why are you trying to dynamically load javascript? Could you solve the same problem by loading some other resource, e.g. by doing an AJAX request?
You've tagged jQuery on your question. It has $.getScript() which does exactly what you're asking for in a purely cross browser fashion. It will load the script asynchronously and then call the specified callback when the script has finished loading and initializing:
$.getScript("defer.js", function() {
// script loaded here
// you can run code here that uses that script
});
If you really want to wait until the DOM is loaded before loading this script (generally not necessary), you could do this:
$(document).ready(function() {
$.getScript("defer.js", function() {
// script loaded here
// you can run code here that uses that script
});
});
Or, to wait until ALL other resources are loaded including images:
$(window).load(function() {
$.getScript("defer.js", function() {
// script loaded here
// you can run code here that uses that script
});
});
If you're interested in some references on when scripts are loaded (particularly with defer and async attributes, you can read this detailed post.

How to test if jQuery and certain other scripts have loaded?

I know about document.ready() but I don't want to wait for some content on external servers like Google Analytics, some ad serving content or anything else that isn't absolutely required for the website. I see this problem on sites that have user comments, and usually every single external piece of content has to be loaded before comments become available to use and even if one of the many CDNs is late, it blocks everything else.
I don't think you need to test it as much as you need to defer it. Here is a really simple example from Google.
(the following code copied from Google)
// 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);
}
// 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;
Essentially, add a new script tag at the documentReady state when you're executing your code already.

Categories