I am inspecting some interesting behaviors of browser, I don't know it's in standard or not. If I put everythin inside <head></head>, the browser will only begin to render the page after all the resouces in head is retrieved.
So I am thinking that put as little as possible things into head is one of the important website optimization techniques, is it right? My question is:
If I put script/css in body or other parts of the html, how can I know that script has been loaded successfully so that I will not be calling a undefined function?
To answer shortly: You should really put the script tags at the very end of the <body> element. Style tags should be put in <head>, otherwise the document will have to be re-rendered every time a new stylesheet is loaded, so you really want them all to be loaded before the document starts rendering.
As for using javascript code that is not loaded yet. Of course you shouldn't bind any events or anything too early, and shouldn't have inline javascript in the page ideally. The solution can be to just use the window onload event to do your initialization, if you really must have inline code in the page.
Related
I have some JavaScript in the HEAD tag that dynamically inserts an asynchronously loading script tag before the last script on the page (that has been currently parsed). This dynamically included script tag contains JavaScript that needs to parse the DOM after the DOM is available, but before all images AND script tags have been loaded in. It's important that the JavaScript starts executing before all JS has been loaded in, because if there is a hanging script, this would lead to a bad user experience. This means I can't wait for the DOMContentLoaded event to fire. I don't have any flexibility as to where I place the first bit of JavaScript that is dynamically including the script tag.
My question is, is it safe for me to start parsing through the DOM right away, without waiting for the DOMContentLoaded event? If not, is there a way for me to do this without waiting for the DOMContentLoaded event?
...JavaScript in the HEAD ... dynamically inserts an asynchronously loading script tag before the last script on the page...
I'm assuming the loader script is inline, meaning that the highlighted bit actually refers to the "current" script element i.e. the loader. This happens since only the html preceding the loader script tag has been parsed and interpreted, so the inserted script tag is actually still in the head and not at the bottom of the page. So the target script is limited to performing DOM operations on preceding elements only, unless you wrap the code into a DOM ready callback... which is what you're trying to avoid in the first place!
Basically you want to load all html so that the page is visible/scannable, start loading images/stylesheets (which occurs in non-blocking threads) and then load any javascript. One approach is to put your target script at the bottom of the page, just pick their order correctly (interactivity first, enhancements second, third party analytics/social media integration/anything else super-heavy last) and adjust for your needs. Technically it still blocks the page load, but there are only scripts left at the bottom of the page anyway (and since they are at the bottom, you would be able to directly manipulate DOM as soon as they're loaded, minus some IE7 quirks).
There is a relevant rant/overview I like to link to that provides decent examples and some timing trivia on use and abuse of DOM ready callbacks, as well as the "other side of the story" on why stellar performance could be of lower value than a sane dependency management framework. The subject of latter is far too broad to be exhausted in one answer, but something like requirejs documentation should give you a fair idea of how the pattern works.
Perhaps another pattern for to consider is building an SPA - single page application which leverages asynchronous access to content chunks rather than the "traditional" navigating between complete pages. The pattern comes with an underestimated but rather significant performance benefit from not having to parse and re-execute shared javascript on every page, which would also address your (valid) concern about third-party js performance. After all, just a good caching policy would do wonders for loading time, but poor javascript code or massive frameworks' execution overhead remains.
Update: Figured this out. With your specific scenario in mind (i.e. no control over markup per se, and wanting to be the last script to execute), you should wrap the insertion of the async script element into DOM into a 0ms setTimeout callback:
setTimeout(function(){
//the rest is how GA operates
var targetScript = document.createElement('script');
targetScript.type = 'text/javascript';
targetScript.async = true;
targetScript.src = 'target.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(targetScript, s);
}, 0);
Due to the single-threaded nature of the environment, js setTimeout callback is basically added to a queue for 0ms-delayed execution as soon as the thread is no longer busy (more thorough explanation here). So the browser isn't even aware of the need to load, let alone execute, the target script until after all "higher priority" code has been completed! And since DOM is operational when the script tag is being added, you will not have to check for it explicitly in the target script itself (which is handy for when it's loaded "instantly" from cache).
The behavior of the following techniques make it safe to parse DOM ...
Using window load or DomContentLoaded event
Declare or inject your script at the bottom of the page
Place "async" attribute on your script tag
or doing this:
<script>
setTimeout(function(){
// script declared inside here will execute after the DOM is parsed
},0);
</script>
Also, these will NOT BLOCK the page loading in DOM.
There is no need to call the DomContentLoaded event when declaring script below any DOM you are depending on UNLESS you are needing to do size calculations or positioning as images/video will change the sizing of things if width/height is not specified.
Here is some scenarios where this works.
DEPENDENT DOM IS ABOVE
<script src="jquery.js"></script>
<script>
$('mydom').slideDown('fast');
</script>
or try this:
<script>
// won't fart
setTimeout(function(){ console.log(document.getElementById('mydom').innerHTML); },0);
</script>
DEPENDENT DOM IS BELOW or ABOVE (dont' matter)
Here's my little test for you to see setTimeout working as its one of those strange things I didn't notice until recently so its nice to see a working example of it.
http://jsfiddle.net/FFLL2/
Yes, you should wait for the user agent to tell you that the DOM is loaded.
However, there is more than one way to do so.
There is a difference between onreadystatechange to interactive and DOMContentLoaded.
According http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html
the first thing the user agent does, after stopping parsing the document, is setting the
document readiness to "interactive".
The user agent does not wait for scripts to be loaded.
When the document readiness changes, the user agent will fire readystatechange at the Document object.
So if the scripts you are worrying about are non-inline, you might hook up with readystatechange.
Talking about cross-browser: This is the spec.
I strongly advise you to fully read the following article which delves in detail into mysteries of script loading and actual DOM readiness and when is it safe to do what with what, also taking into account browser disrepancies.
http://www.html5rocks.com/en/tutorials/speed/script-loading/
I'm confused about where to place JavaScript functions:
When should they be put within the head
When inline within the body
And, when after the closing html tag?
thanks
The rules are fast and loose on this, There is no right or wrong way only better and less-better. (well after the </html> is wrong)
Generally speaking, javascript in the head of the document might block rendering of the page until the file is loaded in some browsers *cough*IE*cough*. This is due to a limit of simultaneous connections. So some people put them before the closing html tag. You can use a library to asynchronously load the javascript to avoid this blocking.
If you're using a library, or checking for the DOM to be loaded before executing code there's really no issue of where it's placed. However if you're not doing that it's probably better to put it at the end.
Javascript can always be safely placed in the head to make the functionality available to the entire page. Note that this can block loading of the rest of the document, so if you are loading very large or external Javascript, you may wish to load them inline near the end of the body.
Javascript placed inline will become available when executed. This allows you to conditionally load JS when page elements are loaded.
Javascript should always be placed in the <head> or <body>, never after </html>.
I agree, never seen (nor could I recommend) after html. Also, as noted, blocking is the concern. What I often go with is one script reference in the head to yepnope (an async js loader and testing tid bit (now included with modernizr)), and a tiny block of inline js at the end of the body tag that loads a bootstrap js file.
In that file, I use another yepnope request to load other needed assets asynchronously, and kick off initialization methods.
I've also taken to putting my Google Analytics code in a final yepnope block, so that it's the last thing to load, even after the js app boots.
So I'm using jquery along with some plugins I wrote.
I do all the initialization in a $(document).ready(function(){}) block however this is executed when the whole DOM has been loaded and is ready to be used.
However that would take long eg. when there is a server load. Or maybe the user clicks a button that has been loaded while the rest of the page hasn't loaded yet (and thus document.ready() hasn't been executed yet) in which case it would do nothing.
So, what if I want a code to be executed right after the related part of the page has been loaded instead of waiting for the WHOLE page to be loaded?
I know placing inline code right after the html that this js operates on would do the trick but what if that code uses a library like jQuery that hasn't been loaded yet?
I know placing inline code right after the html that this js operates on would do the trick but what if that code uses a library like jQuery that hasn't been loaded yet?
That would be the only way. The HTML is parsed from top to bottom. So you can expect every script you included to be accesible after you included it.
Your page should still work without JavaScript anyway, so a user clicking a button extremely fast will just temporarily have a somewhat degraded experience.
That being said, the DOM is basically ready when the HTML document all scripts are loaded. Since you cannot execute meaningful JavaScript before the JavaScript code is loaded (duh), I'd have a close look at page performance. Sending an HTML document and 2,3 JavaScript files should not be slow.
You could also use the old-style inline event handlers, like <button onclick="registerButtonClickEvent()">. However, this would introduce a complex, potentially buggy and hardly testable layer of temporary event holding.
If your <script src="jquery-whatever.js> line precedes the first clickable element in your HTML, it is guaranteed that the jquery library will be loaded and run before the user has anything useful to click on.
Just don't add async or defer attributes to the script element.
The onload event isn't triggered from all html elements, so you're forced to wait for window load. It doesn't matter where you load jQuery since it will have to wait for document to be ready. That total time required to load jQuery plus the rest of the document will be thet same.
I see that Javascript code is normally in heading part of HTML code.
<head>
<script type="text/javascript" language="javascript" src="core.js"></script>
...
</head>
Is it OK to put the Javascript code in a body part of HTML code? I tested it, but it seems to work.
<body>
<script type="text/javascript" language="javascript" src="core.js"></script>
...
</body>
If so, why the examples of Javascript books put the javascript code in heading part?
If not, what's the difference between putting the javascript code in body/heading part?
Not only is it OK, it's actually better, since it lets the content come first.
If your viewers have a slow (eg, mobile) connection, it's better to send the actual content first, so that they can read it while the browser downloads the Javascript.
All the people saying it is better only applies if you are talking about at the bottom of the page (and that is an up for debate thing) from a code quality point of view, it is NOT ok to sprinkle script tags through your html. All references to javascript should be in a single place on the page, either the head (where they should be), or the very bottom (as a perf optimization)
Edit:
Basically, a web page is made up of 3 pieces; style (css), structure (html), and behavior (javascript). These pieces are all very distinct, so it makes sense to keep them as separate as possible. That way if you need to change some javascript, it is all in one place. If it is sprinkled through the file, it becomes much more difficult to find the code you are looking for, and that code basically becomes noise when you are just looking at structure.
It is the same arguments as why not sprinkle db access code all over your page. It has nothing to do with technical reasons, purely an architectural/design decision. Code that does different things should be kept separate for readability, maintainability, and by extension, refactorability (not sure if that last one is actually a word...)
You can do it, and people often do.
For example, people like to put their script tags just before the closing </body> to make web pages render quicker.
Also, if you do a script block after an element is created, you don't need to wait for DOM ready.
Be warned though, don't add, or remove an element from an unclosed ancestor in the markup tree (not including the script block's immediate parent element), or you will get the dreaded Operation Aborted error in IE.
Just something to add on:
I have preference of putting Javascript file right before </body>. My reasons being that:
Content can load and be shown first. If you load huge Javascript files first, which most are meaningless until the page is loaded, the user won't be able to see anything until the JS files are loaded.
Most Javascript code require to work with the UI can only run after the UI has been loaded. Placing the codes at the end of the html file reduces the need to use the onload event handler.
It is very bad habit to place Javascript snippets all over the HTML file. Placing all at the back of the HTML file allows you to manage your Javascript more efficiently.
It is legal according to the spec.
Most examples use them in the header as the headers come first and the browser will be able to parse the reference and download the JS files faster.
Additionally, these are links and are not part of the display, so traditionally, put in the header.
It is perfectly legal but there seem to be some differing opinions about it. Those who say to put all the javascript references in the head argue that the script is downloaded before the rest of the page become visible and dependent on it. So your user will not see an object on screen, attempt to interact with it and get an error because the javascript code is not yet loaded.
On the other hand, the argument goes that it takes longer to load all the script before the user sees the page and that can have a negative impact on perceived speed of your site.
JavaScripts inside body will be executed immediately while the page loads into the browser
Placing javascript at the end of the body will defer javascript load (ie: the page will render faster), but remember that any javascript function used for an event should be loaded before the event declaration, it is mainly because users may be able to fire an event before the page is completely loaded (so before the function is loaded)!
I used to put it in the head, then I've heard that it takes longer for the page to load so I started placing the scripts at the very bottom. However, I found out the most 'clean' way to do it is to place it in the head BUT you place the script inside a document.ready function. This way you have the best of both worlds. It is cleaner because it is in the head and it is not loaded before the content has been loaded, so there aren't any problems performance wise either.
With jQuery for instance, you can do it like this:
$(document).ready(function() {
alert('test');
});
The alert will only popup when the page has been fully loaded, even though the script is in the head.
Why are JS scripts usually place in the header of a document? Is it required by standards, or is it just a convention with no particular reason?
See http://developer.yahoo.com/performance/rules.html#js_bottom
Although past practice has often been to place them in the header for the sake of centralizing scripts and styles (and the like), it is advisable now to place the scripts at the bottom to improve loading speed of the rest of the page.
To quote:
The problem caused by scripts is that they block parallel downloads. The HTTP/1.1 specification suggests that browsers download no more than two components in parallel per hostname. If you serve your images from multiple hostnames, you can get more than two downloads to occur in parallel. While a script is downloading, however, the browser won't start any other downloads, even on different hostnames.
In some situations it's not easy to move scripts to the bottom. If, for example, the script uses document.write to insert part of the page's content, it can't be moved lower in the page. There might also be scoping issues. In many cases, there are ways to workaround these situations.
An alternative suggestion that often comes up is to use deferred scripts. The DEFER attribute indicates that the script does not contain document.write, and is a clue to browsers that they can continue rendering. Unfortunately, Firefox doesn't support the DEFER attribute. In Internet Explorer, the script may be deferred, but not as much as desired. If a script can be deferred, it can also be moved to the bottom of the page. That will make your web pages load faster.
A <script src="url"></script> will
block the downloading of other page
components until the script has been
fetched, compiled, and executed. It is
better to call for the script as late
as possible, so that the loading of
images and other components will not
be delayed.
It depends on what the script is doing. If your code is wrapped in onLoad event then it doesn't matter since it will return almost immediately and not block otherwise you should put it where it fits because the placement does matter.
As for putting it at the end, it does give a little extra time for user to start looking at the page. Just ask yourself a question - does my site work without javascript? If it doesn't, then in my opinion it doesn't mater where you put it since onLoad code will only be executed when the DOM has been fully loaded (that includes binary content like images). If you can use it without javascript then put it at the end so that images can load faster.
Also note that most JS libraries use special code which works around the onLoad problem and uses custom event for this which gets fired once DOM has loaded and doesn't wait for binary data.
Now that I wrote all that, I got a question of my own. Does using say jQuery's
$(document).ready(function () {});
and putting the script tag at the end of page is the same as using onLoad event and putting it at the start?
It should be the same because browser would load all images before loading the script which is the last one in the list. If you know the answer leave a comment (I'm too lazy and it's too late to test it atm).
It's just a convention. It's usually recommended to put scripts at the end of the body so the page can display before loading them, which is always a plus. Also, document.body can't be used until the document is loaded or if you put the script in the body.