I am loading some JS from an external source right before my </body> tag. I am experimenting to see what happens if the server hangs while trying to serve this third party JS. It seems that everything on my page works just fine, but the browser still spins as though the page is still loading. Is there a way to load this javascript in such a way that the browser won't wait on it to declare the page fully loaded?
For reference, I have tried the following two methods to load my JS asynchronously:
<script>
var resource = document.createElement('script');
resource.src = "https://myserver.com/js/myjs.js”;
var script = document.getElementsByTagName('script')[0];
script.parentNode.insertBefore(resource, script);
</script>
and
<script async src="https://myserver.com/js/myjs.js"></script>
An answer compiled from the comments above and my own experimentation:
If you load the third party JS after the rest of the page has finished loading, then the browser will render the page as though it is completely loaded, even if the external resource hangs. One way to accomplish this is to load the JS within a window.setTimeout with a timeout greater than your page's standard load time.
When you are loading external JS through a JS function rather than through a standard script tag, remember that if you have any data- attributes, they belong in the resource.dataset object.
So, in the example above,
<script async data-my-data="someData" src="https://myserver.com/js/myjs.js"></script>
becomes
<script>
window.setTimeout(function () {
var resource = document.createElement('script');
resource.dataset.myData = "someData";
resource.src = "https://myserver.com/js/myjs.js";
var script = document.getElementsByTagName('script')[0];
script.parentNode.insertBefore(resource, script);
}, 5000);
</script>
Note that 5000 as a timeout works for me because my page loads in well under 5 seconds, and I don't need the JS that I am loading in the first 5 seconds. If you need yours sooner or your page takes longer to load, you will need to adjust this number. Also, as #adeneo mentioned above, another way to accomplish the same thing would be to load the js through ajax later.
You can load js by getscript, check this demo
Related
What are the differences between the two solutions below ?
In particular, is there a good reason to favour 2 over 1. (note: Please assume the name of the script to load is known. The question is just about if there is value in creating a minimal script to load a script in the given situation )
1 - Script At The Bottom
<html>
<body>
...
...
<script src='myScript.js'></script>
</body>
</html>
2 - Script at the bottom loads external script
<html>
<body>
...
...
<script>
// minimal script to load another script
var script = document.createElement('script');
script.src = 'myScript.js'
document.body.appendChild(script);
</script>
</body>
</html>
One important feature of the second one is that it allows the browser to finish parsing the page immediately, without waiting for the script to load. That's because the first example allows the script to use document.write to change the parsing state around the <script> tag, while the second one doesn't.
Now, we know that it's at the bottom of the page so that there isn't any important content left to parse, but this is still an important difference. It's not until parsing is done that the browser fires the popular DOMContentLoaded event. In method 1, the event fires after the script loads and executes. In method 2, the event fires before the script starts loading.
Here are some examples. In these demos, a DOMContentLoaded listener changes the background color to yellow. We try to load a script that takes 3 seconds to load.
http://jsfiddle.net/35ccs/
http://jsfiddle.net/VtwUV/
(edit: Maybe jsfiddle wasn't the best place to host these demos. It doesn't show the result until the slow-loading script loads. Be sure to click Run again once it loads, to see what happens.)
Pick the approach that's best for your application. If you know you need the script to run before DOMContentLoaded, go with method 1. Otherwise, method 2 is pretty good in most cases.
1. Script at the bottom
When you use a "synchronous" script tag, it will block the browser from rendering the page until the script is loaded and executed. This method has the following effects:
Regardless of where you put the script tag, the browser cannot fire DOMContentLoaded until the script is downloaded and executed.
Placing such a script tag at the bottom only ensures that the browsers has rendered all content before getting blocked by the script.
2. Script at the bottom loads external script
When you inject a script tag using JavaScript, it will create an "asynchronous" script tag that does not block the browser. This method has the following effects:
Regardless of where you put the JavaScript code that generates the script tag, the browser executes it as soon as it is available without blocking the page. The DOMContentLoaded fires when it should; irrespective of whether the script has downloaded/executed.
The second approach has the following advantages:
The script that injects a script tag can be placed anywhere including document head.
The script will not block the rendering.
DOMContentLoaded event does not wait for the script.
The second approach has the following disadvantages:
You cannot use document.write in such scripts. If you do, such statements might wipe the document clean.
Asynchronous execution does not mean that browser has finished parsing the page. Keep the script executes as soon as it is available clause in mind.
Execution order is not guaranteed. Example: If you load "library.js" and "use-library.js" using injected script tags, it is possible for "use-library.js" to load and execute before "library.js".
Having said all that, there is another method for loading scripts, with three variations:
<script src="myScript.js" async></script>
<script src="myScript.js" defer></script>
<script src="myScript.js" async defer></script>
Regarding Steve Souders's work: he proposed 6 techniques for loading scripts without blocking. The async and defer attributes introduced in HTML5 cover the Script DOM Element and Script Defer techniques and their browser support is more than enough for you to worry about the other techniques.
These two ways of initializing a script are basically the same, although theres no reason to use the second way if you can directly put in the result. However you can wrap the second example in a $(document).ready() method for example which would lead to sort of a lazy loading effect. This basically means that the page would load first and after the loading of the page is finished it would load the script. Or of course you can create a method which initializes a certain script this way. It's useful when you have a large script which is used only in some situations. This would prevent loading it unless you need it, thus decreasing the overall loading time.
This isn't a direct answer to your question, but it's good to know regardless.
The 2nd approach is sometimes used as a library fallback.
For example, you load jQuery from the Google CDN. But, if it were to fail for any reason, load jQuery from your own local copy.
Here's how the popular HTML5 Boilerplate recommends doing this:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.0.min.js"><\/script>')</script>
The first method means that the script tag is hardcoded in. The second method dynamically adds a script tag to the bottom of the page using JavaScript. The benefit of the second method is that you can add additional logic if needed to modify the script tag. Perhaps you might want to load a different script file based on culture, browser or some other factor you can determine in JavaScript. The second method also causes the JavaScript file to be loaded without blocking the loading of the rest of the web page. In method one the page will stop loading when it gets to the script tag, load the JavaScript file, then finish loading the rest of the page. Since this tag is at the bottom of your page it doesn't make too much of a difference.
If you are creating a Windows Store app using JavaScript then the first method is recommended as this will allow the app to bytecode cache the JavaScript file which will make it load up faster.
On my website I have ads from a network that does not load particularly fast. Some browsers won't draw the page unless the ads load, making the website appear slower than it actually is - is there any way to prevent this? As in mark the script as non-essential or do some javascript trick to only draw it once it's loaded? I tried googling a solution, but to no avail.
Also, some ads are added to the site as iframe, some as JS script (much like adsense)
If loading the ads is optional, what you could do is wait to load them and then use ajax to load/add them later with jquery.
The best thing to do here is defer the loading of your ads, and anything else non-essential, until after the page has finished loading.
Attach code to load these to window.onload. That event fires when everything on the page is done loading. You can even defer loading the whole script by adding it to the DOM later. I use jQuery.getScript() for this, but there are other methods.
Load the ad after the DOM has been loaded. You would have your page load normally, then bind a function (JavaScript) which injects the ad(s).
There is also the defer attribute on tags, but it isn't fully cross-browser supported.
JavaScript: Defer Execution
You could try to put your script tags at the bottom of the page, before the closing body tag. http://developer.yahoo.com/blogs/ydn/high-performance-sites-rule-6-move-scripts-bottom-7200.html
Or you could try to load them asynchronously.
In HTML5 (not as much browser support)
<script async src="http://your.com/script.js"></script>
Another way (works with more browsers)
<script>
var resource = document.createElement('script');
resource.src = "//your.com/script.js";
var script = document.getElementsByTagName('script')[0];
script.parentNode.insertBefore(resource, script);
</script>
http://css-tricks.com/thinking-async/
I'm using Head js to load my javascript files in parallel. I added head js to my head and then used head.js("path/to/file/my.js"); but when I load my webpage the script is missing. Only after refreshing a few times does the whole script work properly. Why do I need to refresh it to make it work? Any suggestions would be appreciated!
As the scripts are loaded asynchronously, you can't use it immediately. After you have refreshed the page, it will find the script in the cache, so it will load in time for any code needing it sometimes.
Use the ready method for any code that needs the script:
head.ready(function() {
// any code that needs the script to be loaded first
});
Another way is to mark your library and then get the ready event when your script is loaded. Read more from http://headjs.com/ Labeling scripts.
head.ready("your", function() {
});
head.js(
{jquery: "http://http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"},
{tools: "http://cnd.jquerytools.org/1.2.5/tiny/jquery.tools.min"},
{your: "http://a.heavy.library/we/dont/want/to/wait/for.js"},
// label is optional
"http://can.be.mixed/with/unlabeled/files.js"
);
In order to avoid javascript to block webpage rendering, can't we just put all all our JS files/code to be loaded/executed simply before the closing </body> tag?
All JS files and code would be downloaded and executed only after the all page has being rendered, so what's the need for tricks like the one suggested in this article about non blocking techniques to load JS files. He basically suggests to use code like:
document.getElementsByTagName("head")[0].appendChild(script);
in order to defer script laod while letting the webpage to be rendered, thus resulting in fast rendering speed of the webpage.
But without using this type of non-blocking technique (or other similar techniques), wouldn't we achieve the same non-blocking result by simply placing all our JS files (to be loaded/executed) before the closing </body> tag?
I'm even more surprised because the author (in the same article) suggests to put his code before the closing </body> tag (see the "Script placement" section of the article), so he is basically loading the scripts before the closing </body> tag anyway. What's the need for his code then?
I'm confused, any help appreciated, thanks!
UPDATE
FYI Google Analytics is using similar non-blocking technique to load their tracking code:
<script type="text/javascript">
...
(function()
{
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = 'your-script-name-here.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s); //why do they insert it before the 1st script instead of appending to body/head could be the hint for another question.
})();
</script>
</head>
Generally saying no. Even if scripts will be loaded after all the content of the page, loading and executing of the scripts will block the page. The reason for that is possibility of presence of write commands in your scripts.
However if all you want to achieve is the speed of loading page contents, the result of placing script tags right before </body> tag is the same as for creating script tags dynamically. The most significant difference is that when you load scripts in common static way they are executed one by one, in other words no parallel execution of script file (in old browsers the same true is for downloading of the script too).
If you want asynchonous scripts.
Use the (HTML5) async tag if it is availble in the browser you're in. This is what Google Analytics is doing in the code you posted (specifically the line ga.async = true MDN Link, scroll down for async).
However, this can cause your script to load at arbitrary times during the page load - which might be undesirable. It's worth asking yourself the following questions before choosing to use async.
Don't need user input? Then using the async attribute.
Need to respond to buttons or navigation? Then you need to put them at the top of the page (in head) and not use the async tag.
Async scripts run in any order, so if your script is depending on (say) jQuery, and jQuery is loaded in another tag, your script might run before the jQuery script does - resulting in errors.
Why don't people put things at the bottom of the body tag? If the script is taking enough time to load that it's slowing/pausing the load of the website, it's quite possible that that script is going to pause/hang the website after the website has loaded (expect different behaviour on different browsers) - making your website appear unresponsive (click on a button and nothing happens). In most cases this is not ideal, which is why the async attribute was invented.
Alternatively if your script is taking a long time to load - you might want to (after testing) minify and concatenate your script before sending it up to the server.
I recommend using require.js for minifying and concatenation, it's easy to get running and to use.
Minifying reduces the amount of data that needs to be downloaded.
Concatenating scripts reduces the number of "round-trips" to the server (for a far away server with 200ms ping, 5 requests takes 1 second).
One advantage of asynchronous loading (especially with something like the analytics snippet) is, at least if you would place it on the top, that it would be loaded as soon as possible without costing any time in rendering the page. So with analytics the chances to actually track a user before he leaves the page (maybe before the page was fully loaded) will be higher.
And the insertBefore is used instead of append, because if I remember correctly there was a bug (I think in some IE versions, see also link below theres something in the comments about that).
For me this link:
Async JS
was the most useful I found so far. Especially because it also brings up the issue, that even with googles analytic code the onload event will still be blocked (at least in some browsers). If you want this to not happen, better attach the function to the onload event.
For putting the asynchronous snippet on the bottom, that is actually explained in the link you posted. He seems to just do it to make sure that the DOM is completely loaded without using the onload event. So it may depend on what you're scripts are doing, if you're not manipulating the DOM there should be no reason for adding it on the bottom of body. Besides that, I personally would prefer adding it to the onload-event anyway.
I want to execute a script after the whole page has loaded, when it's complete.
The current way is:
window.onload=document.getElementById('loaded').value=1;
Which is not good, as some images are still in load, and the page has not completed loading truly. What I am doing wrong?
Certainly doesn't work for me in Chrome and Firefox. The thing is I launch a code after, that returns status 204, and this blocks future loads. But it seams this 204 status is returned way before the page has finished loading. So I need to execute my code after the page has truly loaded.
EDIT
setup a page, that does framebreaking
<iframe id="myframe" height=1 width=1></iframe>
<script type="text/javascript">
window.onload=document.getElementById('myframe').src='http://link to a frame braker page';
</script>
when you put the above code to a page, it loads the iframe before the page is fully loaded. Simply put an alert in the iframe page, and try out on a slower server where your parent page contains large images etc..
window.onload=document.getElementById('loaded').value=1;
You've forgotten to turn that into a function. What you're saying is:
document.getElementById('loaded').value= 1;
window.onload= 1;
Obviously that's not very effective as a load detector. What you meant was probably:
window.onload= function() {
document.getElementById('loaded').value= '1';
};
The window.onload event should wait for images to load before it is fired:
The load event fires at the end of the
document loading process. At this
point, all of the objects in the
document are in the DOM, and all the
images and sub-frames have finished
loading.
Source: Mozilla Dev Center: window.onload
You may want to check out the following Stack Overflow post for further reading:
Execute Javascript When Page Has Fully Loaded
UPDATE:
The reason why your implementation is not working has identified by bobince in another answer. The solution is to use:
window.onload = function() {
document.getElementById('loaded').value = '1';
};
If you can use Jquery, have a look to FrameReady plugin.
Check this SO question. for further information