Improving front-end performance using the onLoad event - javascript

I've been trying to improve our front-end webpage performance and trying go use webpagetest for some insights. Our current page load time is 8 secs.
Here is a waterfall view of our site - http://i.imgur.com/D4sPLfs.png
The blue line indicates the load event fired which decides the load time.
And here is a waterfall of another site which has a page load time of 4secs - http://i.imgur.com/NuO1Mao.png
The waterfalls of both the sites look similar apart from one glaring difference - The blue line (load event fired) of the second one is way earlier even though a lot of content is loaded after the onLoad firing event.
Am I right in thinking that if somehow I can make the onLoad firing earlier on my site, I will see improved perceived performance for the user? If yes, how do I go about it?
We're already using lazyload.js for lazy loading images
Most of our third part js files (Google Ads / Analytics) are being called near the bottom of the body element
Thanks a lot!

There is the alternative "domready" event, which is also what jQuery uses. It is triggered when the DOM tree was built and does not wait for external resources (mostly images) to load, what the onload event does.
With that loading time it's pretty likely you are using a JS framework that is supporting the domready event already, which you should consider using, then.
You will likely have to rewrite a good portion of your scripts, mostly if you are expecting image width/height to be correctly set.
If you have access to jQuery, you can use something like that:
$().ready(function() {
loadHandler();
});
If jQuery is no solution, you should propably take a look at this extraction of jQueries domready function, because there are a lot of quirks to look out for.

Related

How does $(window).one('load') work, and how does it fail?

As some background, I am working on building a web slider activity that fits into/extends another piece of software that outputs HTML. The key point being I have very little to no control over how the software outputs it's HTML Elements, but I can add arbitrary JavaScript and HTML elements on top of what the software outputs.
What I am trying to do is delay the loading of some images that I want to add until after all the software's outputted elements are loaded. So far I have it working by waiting to load the images until after the window load event is fired. Like so:
//-----Simplified example-----
$(document).on('ready', funciton(){
//Some stuff to set things up
$(window).one('load', function(){
$('#SomeDiv').append('
<img class= "someClass"
id="arbitraryImage1"
src="folder/image1.jpg"
');
});
});
Though it is working right now I'm not sure what will happen if something goes wrong. The HTML outputted by the software has a bad habit of including things that it might not need as well as occasionally not loading images on slower connections. The majority of the time if it does fail the user will not notice, so it isn't an issue. However I would like to know how $(window).one('load', function(){})behaves when a problem arises, so that I can work around the error or at least make the activity fail graciously. Any assistance or links to documentation would be appreciated, the generic-ness of 'window' and 'load' brings up a lot of irrelevant information when googling.
To summarize:
What is the behaviour of $(window).one('load', function(){}) when the window fails to load a resource (image, css, etc.)?
Good question. The documentation says:
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, scripts, links and sub-frames have finished loading.
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload
But in practice, you'll find that the load event fires after all assets queued to load when the document was originally parsed (stylesheets, external scripts, img tags) have loaded, or failed loading. As long as no requests are still pending, the fact that these assets have loaded successfully or not has no bearing on the load event being fired.
The documentation is in need of a clarification, in my opinion, as it doesn't address your question.
If image fails to load, then there will be just no image in your image, if it will be unable to find SomeDiv, then nothing will be appended anywhere, generally if javascript function fails to some reasons - then nothing bad will happen, just broken functionality won't work, meaning load will still be done, just console will be telling about errors

Does dynamically prefetching a resource using DOM injection work or make sense?

This is largely a theoretical question, for which I do have a practical purpose. I first am looking for some conceptual answers before diving into practice, as perhaps the idea itself does not make sense.
Imagine a slideshow that is entirely javascript-based. Users see a large image on their screen and click to move to the next large image. Upon clicking, the next image is loaded and inserted into the DOM, replacing the previous one.
I recently learned that prefetching directives can help in speeding up the loading of resources that are very likely to be used next. Note that I said resources, not pages. The slideshow is a single page.
In an image slideshow, it is very obvious that it is likely that the next image is needed, thus if image1 is on screen, I could dynamically add this to the DOM:
<link rel="prefetch" href="http://img.mysite.com/img2.jpg">
My questions regarding this idea:
Would it work at all? Do browsers accept this directive when it is dynamically inserted in the DOM at run-time? Would it trigger the prefetch?
Is there a possibility of timing conflicts, where if prefetching would indeed work, it did not finish in time before the use does the "load" without prefetching? Obviously this can happen, but will it have unwanted side effects?
Will specific events such as image onload still work correctly, or are they never triggered in the case of a successful prefetch (assuming it works at all)?
I did a lot of searching but I am unable to find answers on this specific situation of dynamically injected prefetch hints.
onload always gets triggered, even if the image is coming from cache. You do not have to worry about timing effects or race conditions, any such behavior would be a browser bug.
As mentioned in comments, rel=prefetch is not the only way of achieving pre-fetching. It works though even when dynamically inserted into the DOM. After all, you could fetch the image without the prefetch attribute and hide it.

Perform time consuming tasks before window.onload

I submitted my HTML5 game for a HTML5 game platform for QA review and got the following feedback:
You should not perform time consuming tasks before window.onload but the actual is: DOM is blocked.
I am not sure what this review means. What I am doing now is:
$(window).ready(
....
);
So this is the entry point of all the code. So what is the difference between $(window).ready and $(document).ready() and window.onload. Do they follow a fixed order as to when they are triggered? And what does DOM is blocked mean?
dom ready vs window.load
$(document).ready(function(){}); is triggered until the HTML is fully parsed and rendered, but before all Assets (images, iframes and so on) are downloaded. $(window).load is executed right after all images are downloaded.
This means: $(document).ready comes always before $(window).load.
DOM is blocked
Is quite untechnical and not really the truth. You showcase, that you can manipulate the DOM at "DOM ready" and acutally this is the right event for doing so. What they mean is the following: As long as a script is executing, the browsers main thread is blocked. Which means, that the browser can not render/paint anything in this time and the browser becomes unresponsive.
The idea behind this advice is the following:
If you are executing a script on DOM ready, painting stops and will be delayed after script execution. The user might see some sort of your UI, because at this time the DOM is already rendered and in most cases also the CSS is, but not the images. But if you delay it after window.onload the browser can also render images and iframes, before you block the main thread, which means the user might see a fully rendered site/game sooner, although it isn't technically ready yet.
My 2 cents
Wether this is a good approach or not, really depends on a lot of circumstances. If your JS does a lot of UI things, it is bad, because the user won't see the final UI sooner, the user will see it later. If your JS is important for the page to work and the page has some bigger images, it is quite stupid to delay executing script. Consider a mobile user, he might already see the UI to start the game, but your click/tap event isn't yet bound, because there is a big image at the end of your page, which still needs to load?
If you have a performance problem fix it, don't delay it to antoher point, this will also block the main thread. But what you can do: If you have a lot of scripts, you can split those tasks into chunks and execute them at the point, when they are really needed and not initially. For example: You have a Menu and this menu has a hidden sub menu, which needs initially some special dom manipulation. Don't do this at dom ready or on window.load, do it right before it opens for the first time.

Progressive enhancement, behavior when pages are not fully loaded yet

I'm developing sites using progressive enhancement implemented completely in jQuery.
For instance, I'm adding onclick event handlers dynamically to anchor tags to play linked MP3 files "inline" using SoundManager and popping up Youtube players for Youtube links, through $(document).ready(function()).
However, if the user clicks on them while the page is loading, they still get the non-enhanced version.
I've thought about hiding the relevant stuff (via display: none, or something like that) and showing it when loaded, or putting a modal "loading" dialog, but both sound like hacks.
Any better ideas? I feel I'm missing something completely obvious here.
Regards,
Alex
I haven't tested this, but you could try live. The thinking is that you could put your click handlers outside of document.ready so they get executed right away. Since live uses event delegation to achieve it's functionality, you don't really need to wait for the DOM to be ready, and any clicks that are made while the page is loading should still be captured by the event handler.
If that doesn't work, you could try putting the Javascript script tags directly underneath whatever they need to bind. It's not pretty, but it will pretty much eliminate the problem.
Assuming you have used good judgement and people are falling for the non-enhanced version just because the delay is too long then I would use CSS to disable the controls. The CSS will load almost right away. Then using Javascript I would toggle the CSS so the controls are re-enabled.
However, my first reaction is that if the user can click it while the page is loading, then your page or connection is too slow. However, if this is seldom the case--less than 1% of the time--then you can shrug it off as long as the user can achieve his goal, that is listen to his music. I say this because once the users realizes that a better experience awaits half a second later, he will usually wait for Javascript to render and then click.
I take the opposite stance from aleemb regarding using CSS. If you use css to disable the controls, then anyone who has javascript disabled or is using accessibility software will be unable to use those controls without disabling your stylesheet entirely.
You could use a very small inline javascript right before the closing body tag to hide the elements via js really quickly. If it's inline and doesn't have to load external resources it will be very fast, generally faster than a user can click.
However, I do agree with aleemb that if your users are able to mentally process the page and make it to the control they want to click before your js is loaded, there's probably a deeper problem with the way your page is loading. Look into ways to decrease load time: compressing image files, gzipping html/css/js files, minify your javascript, combine images into sprites, etc.
I'd suggest following Paolo Bergantino's advise - event delegation is the way to go to avoid the problem altogether.
I had a similar issue where event delegation couldn't do the job - you can read about that here.

How do you execute a JavaScript function when the page has fully rendered?

How would you go about executing a JavaScript function when the page is fully rendered (Displayed) I know that the onLoad event executes when the page is loaded but Before it's rendered.
I've previously solved this problem by using a timeout with a 0 interval, which seems to work usually, but seems a little inelegant to my delicate sensibilities.
Is there a proper way to do this?
I'm using prototype as my JavaScript framework so answers that involve that are helpful, however I would have thought that this would be built into JavaScript.
The onload event fires when the page is fully rendered (including dependancies such as images).
Perhaps you are confusing it with Prototype's dom:loaded event (which fires when the DOM is loaded but before all the dependancies have been included)?
(To be honest, this sounds like an X-Y problem.)

Categories