Google is wrong about defer? - javascript

In this post:
Why google is using the term "Render-Blocking JavaScript"?
#jaffa-the-cake is asking in a comment to someone:
"Which piece of documentation do you consider incorrect?"
Let's take for example this documentation:
https://developers.google.com/speed/docs/insights/BlockingJS
And now let's take for example what they are saying about "defer":
The loading and execution of scripts that are not necessary for the initial page render may be deferred until after the initial render or other critical parts of the page have finished loading. Doing so can help reduce resource contention and improve performance.
Note that the article is about "Remove Render-Blocking JavaScript", so with the word "may" they mean that you COULD use defer.
With "defer" on a script tag, you will NOT defer "the execution until after the initial render of the page have finished loading". It can be the case, but not necessarily.
"Defer" will defer the execution until after the initial html is in the DOM, but that's something different than "render". The execution will take place after the (preceding) html is in the DOM and before DOMContentLoaded, but that does not mean: "render of the page have finished loading". It would be correct if they would use the term "html parsing of the page have finished".
An example which confirms the theory of above:
INDEX.HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
Some HTML line and this is above the fold
<script src="script.js" defer></script>
</body>
</html>
SCRIPT.JS (from cache!)
// Synchronous delay of 5 seconds
var timeWhile = new Date().getTime();
while( new Date().getTime() - timeWhile < 5000 );
In case the browser will take script.js from cache then "Some HTML line and this is above the fold" will be shown AFTER 5 seconds! So that means the initial render of the page have NOT finished loading yet (while using defer). So in my opinion that means the documentation is incorrect.
p.s. Without script.js from the cache, a browser will have time to finish rendering of the preceding html. The file script.js first has to be downloaded, so that's what gives the browser extra time. With caching, there is less time between "done parsing html" and starting with the "javascript execution", so then there is a chance that "javascript execution" already starts before "finishing rendering of the preceding html". So in case of speed gain, you could even consider in this example to disable caching, so the rendering of the preceding html will be faster.
I have a lot more tests / examples which proves other parts in other documentation (about rendering) of Google are incorrect (in my opinion), but i will keep it clear in this post by using 1 example.
If you are disagree with me, please don't give only a negative reputation, but at least give a comment why you think it's incorrect and which test you did to confirm it. I'm already trying to convince some people at Google that they are incorrect in my opinion, but they are kind of offended by that. Of course i would not say that they are incorrect if i didn't put a lot of time / energy / testing in it and if i would be pretty sure about it. Until now they are saying to me: "consider that the misunderstanding may be yours", so i feel like a small boy "fighting" against a big wall. For me it's not about to get right in the first place, but i see so many people around me (they are already for many years working in IT) struggling with the subject rendering and i can understand it, because the documentation about it is very confusing. That's also why i dived deeper into it, because it was also getting too confusing for me, so i wanted to understand it better.
And if i am wrong, just convince me with arguments and i am the first who will say i was wrong.

After re-reading your question and the linked quote I'm seeing where you are coming from, and why this quote can be misleading. For reference let me put the quote below with the title included:
Defer loading of JavaScript
The loading and execution of scripts that are not necessary for the initial page render may be deferred until after the initial render or other critical parts of the page have finished loading. Doing so can help reduce resource contention and improve performance.
You already understand this, but I'll link it for a reference on how defer works.
As you mentioned, yes the execution of JavaScript in defer and in general is always render blocking, and rather defer does not block the DOM parser.
The reason why the quote is misleading/confusing is because of the sections in bold:
The loading and execution of scripts that are not necessary for the initial page render may be deferred until after the initial render or other critical parts of the page have finished loading. Doing so can help reduce resource contention and improve performance.
The section "The loading and execution of scripts that are not necessary for the initial page render may be deferred until after the initial render". While not an incorrect statement, is misleading because but the performance gain is really directly due to the parser not getting blocked.
This can be clearly shown using the official documentation on defer
A more direct and more clear way to describe this would be as you mentioned:
The loading and execution of scripts that are not necessary for the initial page render may be deferred until after the initial parsing or other critical parts of the page have finished loading. Doing so can help reduce resource contention and improve performance.
That makes it clear that the performance gain is due to the parser being deferred. It also is more inline with how defer specs describe it and the befits of defer:
If the async attribute is not present but the defer attribute is present, then the classic script will be fetched in parallel and evaluated when the page has finished parsing. If neither attribute is present, then the script is fetched and evaluated immediately, blocking parsing until these are both complete. (W3C)

Related

Are deferred scripts executed before DOMContentLoaded event?

Upon defer attribute MDN says:
This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded. The defer attribute should only be used on external scripts.
On DOMContentLoaded MDN also says:
The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets...
So DOMContentLoaded is fired before CSSOM is ready. This means deferred scripts are executed before CSSOM is ready. But if that's true the scrips must not be able to get correct CSS property values and must not apply CSS correctly. But it's not true, we know all deferred scripts work well.
So is MDN documentation technically incorrect?
Where can I find the official documentation of DOMContentLoaded`? I searched in https://dom.spec.whatwg.org/ but couldn't find it.
P.S: Please note that google says that CSSOM is built before executing any inline javascript
But Google is technically incorrect. Inline JavaScript gets executed before CSSOM is ready. And from my tests, I found that MDN is correct and if js files(both deferred and non-deferred) are downloaded before CSS files(or js is inline) then js is executed before CSSOM is ready. So js might handle styles incorrectly. To avoid that we need a forced reflow before all js logic.
So if a user visits our website with all js required already cached and CSS not cached OR js gets downloaded before CSS then (s)he might see an incorrectly rendered page. To avoid this we should add force reflow in all our websites' js files.
I didn't really read the spec though. The following are based on actual behaviors of Chrome (observed on Chromium 68, Ubuntu). Behaviors may vary among browsers, if they were just undefined in specifications. For example in 2010 scripts don't always wait for proceeding stylesheets. I assume agreements had been achieved and behaviors had been standardized over the years.
The defer scripts are executed after domInteractive, before domContentLoaded; it's sequential.
domInteractive and domContentLoaded are two timestamps which could be viewed in Chrome devtools' Performance (previously Timeline) tab. Probably also in other similar tools, but I haven't tried.
domInteractive is the point when HTML parsing and initial DOM construction are finished (and all "sync" scripts have finished executing). document.readyState changes from 'loading' to 'interactive'; a readystatechange event fires on document accordingly.
All defer scripts are executed in their appearing order. Then comes domContentLoaded, a DOMContentLoaded event fires on document.
DOM & CSSOM construction don't rely on each other; but sync scripts may introduce dependencies.
Each sync script, internal or external, waits for preceding stylesheets to be parsed (of course, after fetched).
Yes, sync scripts are not blocked by subsequent stylesheets. MDN and Google and other articles say "scripts depend on CSSOM to be ready"; they (probably) didn't mention that only preceding parts are depended.
P.S: Please not that google says that CSSOM is build before executing any inline javscript
Google didn't say that (at least, as of the time I read this article).
On the contrary, before one sync script is fetched (if external) and executed, any code following it, HTML, stylesheets or other scripts, can't be parsed/executed/constructed. They block anything subsequent to them.
So, in specific cases, eg. without sync scripts, DOMContentLoaded event may fire before or after CSSOM is ready. That's what MDN means by saying "without waiting for stylesheets".
defer/async scripts don't care about stylesheets at all.
Different from sync scripts, defer/async scripts don't wait for preceding stylesheets, and don't block subsequent stylesheets/scripts either. They are removed from those "dependency chains" completely. You can't rely on any proceeding stylesheets to have been parsed.
The differences between defer/async:
as stated above, defer scripts have predictable execution time; the DOM has been ready. They are also promised to execute in order.
Update:
defer scripts are added to the end of the list, says W3C's spec (the 20th item)
(also in WHATWG's spec)
async scripts have no promise on execution order; each async script would be "queued to execute" as soon as it is fetched; once the render process is idle, they are executed. (To be exact, different types of resources have different priorities. The spec provides precious requirements)
These should well explain hinok's two examples, the former async (from Google) and the latter defer。
I don't have much experience on working with CSSOM at page loading (I do operate on DOM at page loading, though), so I can't provide reliable advises. It seems "load event on window" or "force reflow early" might work.
I use deferred script loading. There was a lengthy technical explanation from some guy who is a well known website performance guru. He clearly states that deferred is the way to go (for this and that technical reason, backed by all kinds of data and charts, that many people seemed to feel was wide open for debate, re: async).
So I started working with it. Deferred scripts have the advantage of downloading async, but executing in the order presented, which can be a problem with async (e.g. you can load your app bundle before your vendor bundle because you don't control the execution order of async scripts just by saying "in this order").
However, I found out right away that although this solves that problem, this could mean, depending on how you grab your bundles, the CSS bundle isn't loaded. So you can end up with unstyled content, depending on how you set things up. Note that for defer, they also say that you shouldn't be writing to the dom etc. in those scripts (which again makes sense in terms of your documentation).
So it would seem your documentation is correct. The effect is easily reproduced.
How do I get out of it; the most basic way, is like this:
<script src="css.bundle.js"></script>
<script src="vendor.bundle.js" defer></script>
<script src="angular.bundle.js" defer></script>
<script src="app.bundle.js" defer></script>
This makes sure that the css loads in first, so your home page and so on will show up nicely, and also ensures that (although all three are loading async), that app.bundle will execute last, ensuring all other dependencies are in order.
So, you take the absolute bare minimum of CSS required to kick over the app, create that as a bundle, and load it first, before anything. Otherwise you can bundle in your CSS per module/component, and so on.
There's a lot more to this topic and I could probably be doing more, but again (I will try to find the reference), this was overtly recommended by that performance wizard, so I tried it and it seems pretty effective to me.
Edit: Fascinating, while looking for that reference (which I haven't found yet), I went through a handful of "experts" on the subject. The recommendations differ wildly. Some say async is far superior in all regards, some say defer. The jury really seems out on the topic, overall I'd say it probably has more to do with exactly how you build out your scripts than whether one is actually better than the other.
Edit again: Here's some more evidence. I ran a performance analyzer on a stub website using the above simple loading sequence, deliberately making the scripts naive so they'd be visible in a timeline.
Here's an SS of the result: there are four yellow boxes here. The first three are the evaluations of the scripts. The fourth one (when you mouse over it in the tool, this is just the SS remember) is the DOMContentLoaded event (the one with the red corner).
DOMContentLoaded can be fired before CSSOM, source
The domContentLoaded event fires shortly after the HTML is parsed; the browser knows not to block on JavaScript and since there are no other parser blocking scripts the CSSOM construction can also proceed in parallel.
Article on Google Developer describes async instead of defer but in the case of your question, it doesn't change anything because based on Steve Sourders article on perfplanet
DEFER scripts execute after DOM Interactive.
and his comment under his article
[...] the spec says that DEFER scripts run after domInteractive but before domContentLoaded.
You can make your own experiment, look below for code using defer and timeline
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.3/angular-material.css">
</head>
<body>
<h1>App</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap.js" defer></script>
</body>
</html>

Any good reason not to use <script defer> TODAY?

Once upon a time, there were many heated debate on <script> in <head> or <body>.
Many SO posts had already pointed out the best practice / rule of thumb is to place the <script> before end of <body>for not blocking the html parser, resulting faster first screen paint and quicker DOM access for client, and thus a better UX.
This must be a duplicate╰(‵□′)╯
Wait ... <script> can be deferred now, actually for quite a while !
Old posts said
deferred script may results JS dependency issues
No, it won't. It retains the order on execution immediately when the DOM gets parsed.
It doesn't work cross vendors
Yes, it once was, but today it's almost supported by all major browser vendors: http://caniuse.com/#search=defer, besides may have some problem with IE<10 as the comments point out.
However, the benefits it offers seem obvious, at least to me, as it downloads the script in parallel at earlier time(before start parsing the DOM), thus no need to request the script later and shortens the time it takes to bring the whole page interactive.
To be short, this question is similar to: Any good reason not to use
<head>
...
<script src='cdn/to/jquery' defer>
<script src='cdn/to/bootstrap' defer>
<script src='script/depends/on/jqueryandbootstrap' defer>
</head>
instead using this:
<body>
...
<script src='cdn/to/jquery'>
<script src='cdn/to/bootstrap'>
<script src='script/depends/on/jqueryandbootstrap'>
</body>
note: This might be an "ancient" topic with lots of discussions. However, as web technology moves really fast, browser vendors align better and more consistent with new web specs, many old stackoverflow answers may not keep up-to-date.
Yes, but only because you're using jQuery.
jQuery doesn't work with defer because it tries to fire as soon as the page becomes interactive. They can't fix it any time soon (I raised that bug over a year ago) because changing the ready behaviour to work with defer will break lots of components that rely on jQuery's ready event firing on interactive (i.e. before deferred scripts have finished loading).
If you're using a more modern framework (React, Angular 2, Polymer, Vue, or just about anything else) then go for it - or even go to the next step and use <script type=module in new browsers and a legacy bundle in <script nomodule defer... for IE.
As noted here you should take browser support into account, as some of them don't really support it. There are also some well known bugs in some versions like this one in IE<=9.
If your goal is not to support old browsers (find full support list here) then there is no real reason for not picking defer today.

When does the browser's event loop start?

I'm using a framework which features auto-connecting to server on page load. I can disable it by passing options arguments, but the line that confuses me is this:
You can prevent this initial socket from connecting automatically by disabling io.sails.autoConnect before the first cycle of the event loop elapses.
My questions are:
When does the first cycle of the event loop elapses?
Is this behaviour the same across ALL modern (IE9+) browsers?
I have a bunch of scripts (in <body>) loading between the lib and my entry file. Does this affect when the first cycle elapses? EDIT: Yes, it does.
How can I ensure my code runs before the first cycle elapses?
Is this kind of implementation of auto-connect considered good practice?
The documentation for the source file is a little more explicit; it says "This can be disabled or configured by setting io.socket.options within the first cycle of the event loop."
Basically what's happening is that there exists within the library a setTimeout(fn, 0) call, which is idiomatic for starting a parallel process. However, in the JS standards it's explicitly stated that JS is single-threaded: in other words, even though setTimeout and setInterval are asynchronous they are not actually parallel in the sense that any of their code will be executing simultaneously with any other code. So they wait until the current function is over before they execute. This queueing mechanism is known as the JavaScript event loop.
I believe that what you are asked to do by the script author is to modify the source to include the relevant change, perhaps at the bottom of the file for your convenience.
It is also likely that a similar effect will be achieved by putting a <script> tag underneath the one that loads the given JS. This has not been explicitly standardized by HTML 4, but may be implicitly standardized in the new HTML 5 spec (it's a complicated interaction between different parts of the specs).
In terms of HTML5, it looks like the current specs say that there is a afterscriptexecute event and a load event which occur immediately after any remote script is loaded (or, if it's an inline script, the load event is scheduled as a task -- I am not sure when those occur). So you might be able to guarantee it without modifying the script by instead doing:
<script>
function do_not_autoload() { /* ... */ }
</script>
<script onload="do_not_autoload()" src="./path/to/sails.io.js"></script>
but I'm not sure what the compatibility table for script#onload is going to look like.
I made you a jsfiddle which can be used to grab a 'fingerprint' for different browsers to get an idea of what evaluation orders are out there in the wild. The * is the document.body.onload event. On my system it produces:
Firefox 32.0.3 : cafdbe*
Chrome 37.0.2062 : cafd*be
IE 11.0.9600 : cafd*be
In other words,

Google AdSense JavaScript causing multiple page-loads?

Update
Ok - I now know where the multiple page loads are coming from! (However, the mystery is not yet solved).
It seems that immediately after a request is made to a page containing AdSense ads, Google makes a request for exactly the same URL (one or more times)
e.g. this is what the logs look like (note requests from Mediapartners-Google):
2011-07-20 09:50:20 xxx.xxx.xxx.xxx GET /requestedURL/ 80 - xxx.xxx.xxx.xxx Mozilla/5.0+(Browserstring removed) 200 0 0 1140
2011-07-20 09:50:20 xxx.xxx.xxx.xxx GET /requestedURL/ 80 - 66.249.72.52 Mediapartners-Google 200 0 64 218
2011-07-20 09:50:22 xxx.xxx.xxx.xxx GET /requestedURL/ 80 - 66.249.72.52 Mediapartners-Google 200 0 0 171
(I should have paid more attention to the IIS logs, rather than my own application logs - it just didn't occur to me that these multiple, identical, simultaneous request could have been coming from different sources). This also explains why I couldn't find anything strange when analysing the request with WireShark, and why fiddler didn't show anything strange.
So the question for the bounty now becomes:
Why is google making these requests so quickly after the page is requested? (I know they need to asses the page for content, but immediately after, and multiple times sees like abuse to me.)
What can I do to stop this?
And out of interest:
Has anyone else seem something similar in their logs? (or is this something weird with my AdSense account)
Ok, I'll apologise in advance for the length!...
This question is realted to this one, regarding Google Adsense Javascript code causing errors. (of the form Unable to post message to googleads.g.doubleclick.net. Recipient has origin something.com)
I won't duplicate all of the information there, but the conclusion seems to be that the AdSense JS is buggy. (please read the question for background if you have time).
I knew about this problem for some time, but decided to live with the JS errors rather than pulling AdSense from the site.
However, Recently I noticed that in my ASP.NET MVC2 application, Controller Actions seemed to be called twice per page request (sometimes even 3 times). Odly, it was only happening on the production server. After some thought I relalised that one difference between the Dev and Production environments was that the AdSense javscript was only active in production.
To test this I removed all adsense code from one of the production pages, and lone behold, the multiple-page-load problem went away!
I thought that perhaps it was the fact that there were general JS errors on the page that was causing the problem, so to test this I introduced some simple errors into my own JS code, however this did not cause the multiple-page-load problem to reappear.
One known situation where pages can be called multiple times per request is when there are image tags with empty src attributes, or external resource references with empty src attributes. Crucially, The most upvoted answer to the AdSense JS Bug question notes that:
"The targetOrigin argument in this call, this.la is set to
http://googleads.g.doubleclick.net. However, the new iframe was
written with its src set to about:blank."
This seems eerily similar to the empty src issue.... This seems too much of a co-incidence, and currently I'm of the opinion that this is the problem.
[EDIT: This was a red herring]
However, I've no idea wehre to go from here. These multiple action calls are causing real problems (I'm having to use code blocking, serialised transactions, and all sorts of nasty hacks to limit adverse effects). Of course, I could be barking up the wrong tree entirely - I'm puzzled that I can't find any other references to this, given the ubiquity of AdSense, and the nature of the problem (but then again the conclusions of the AdSense JS Bug question are also surprising). I would love this to turn out to be a stupid mistake on my part, so I need a sanity check.
I'd like to ask the community:
Has anyone else experienced this problem?, or can anyone who is using AdSense replicate and confirm it? [See note below]
Assuming the problem is what it seems, what can I do? (other than pulling AdSense of course)
If not, then what might be causing this?
To Sumarise:
- My actions are being executed 2 (sometimes 3) times per page request.
THIS ONLY HAPPENS WHEN GOOGLE ADSENSE ADS ARE PRESENT
I removed all AdSense JS and introduced an error into my own JS : Actions are called only once...
A similar problem can happen when empty src properties are present on the page
An answer to a previous question sumarises that the AdSense JS sets a src="about:blank" on an iFrame
I have come to the conclusion that the src="about:blank" from the AdSense code is the most likely source of the problem.
If I disable JavaScript on the browser, the problem goes away
Just to document the things I have ruled out:
This is happening across browsers: Chrome(12) Firefox(5) and IE(8).
I have dissabled all plugins on browsers (YSlow, Firebug etc...)
There are no empty src (src=""/src="#") for images, or other external resources in the html in my code
There are no empty url references in the css ( url('') )
It's unlikely to be server side code/config problem, as it doesn't happen in Dev (and of the few differences between dev and production is the absence of AdSence JS in Dev)
Note: For anyone looking to replicate this, it should be noted that, strangely, when the multiple action calls happen Fiddler shows only one request being sent to the server. I have no idea why this should be the case, but the server logging doesn't lie :) Perhaps someone who has prior experience with this problem when caused by empty src attributes in img tags can say whether they have seen the same behaviour with Fiddler.
Requested extra information
HTML (#Ivan)
Here's how I'm implementing the Adsense (ids removed)
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<div class="ad">
<%if (!HttpContext.Current.IsDebuggingEnabled) { %>
<script type="text/javascript"><!--
google_ad_client = "ca-pub-xxxxxxxxxxxxxxx";
/* xxxxxxxxxxxxxxx */
google_ad_slot = "xxxxxxxxx";
google_ad_width = 728;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<%} else { %>
<img src="/Content/images/googleAdMock728x15_4_e.gif" width="728" height="15" />
<%} %>
</div>
This is being inserted by a RenderPartial in the View:
<% Html.RenderPartial("AdSense_XXXXXX"); %>
TCP Logging (#Tomas)
So far I have done a wireshark capture:
on client when requesting page on production with problem
on client when requesting page on production without problem (i.e. Adsense Removed)
I can't really see a significant difference between the two (although my network skills are not great). One thing to note is that they both seem to have a TCP retransmittion of the HTTP request immediately after the initial request - I don't know the significance of that. I can confirm though that in case 1 the server logs reported 2 executions, and in case 2 only one execution.
Next I will try TCP logging on the server side in both cases, and post results here.
Mediabot is the name given to the web crawler that Google uses to crawl webpages for purposes of analysing the content so Google AdSense can serve contextually relevant advertising to the page.
In my experience, it is impredictable and, yes , it can be pretty heavy and annoying.
If you don't want Mediapartner bot to access a specific page, you can disallow it in your robots.txt with:
#
# disallow adsense bot
#
User-agent: Mediapartners-Google
Disallow: path to your specific page
This will have the drawback of service untargeted ads from that specific page.
If you are seeing this pattern always on the same page with different query string, adding the canonical rel could ease the pain.
If you can't resolve this issue, and you see it as an abuse, don't esitate to ask help in the Crawling Indexing and Ranking Google support.
Given that the behaviour that you are observing appear to be hard to avoid, can we rather focus on workarounds?
Can you differentiate requests based on UserAgent, and thus filter out requests.
Could that be a viable approach for you?
If so then you could probably base upon this approach: http://blog.flipbit.co.uk/2009/07/writing-iphone-sites-with-aspnet-mvc.html
Here they detect iPhones, but the consept is the same for Mediapartners-Google bot.
Aside from the embedding of the AdSense code itself, there are two things related to AdSense that differ in your two test cases:
What else happens when !HttpContext.Current.IsDebuggingEnabled? This appears to be the de-facto production flag; maybe there is some other nuance somewhere that is happening that depends on this same flag.
Is it possible that Html.RenderPartial("AdSense_XXXXXX") is somehow causing your Controller to jump back to the beginning of its execution?
From your description, it seems like the execution is happening twice on the server but only one request is being sent from the client. This implies a server error, and these two lines are the crux of your AdSense triggering. To further narrow it down, try embedding the AdSense partial directly instead of calling Html.RenderPartial(). If that doesn't change the result, it might be worth a sanity check on what else switches on HttpContext.Current.IsDebuggingEnabled.
Failing that, it might be helpful to know whether your server-side logging takes place as the request is received, before the response is sent, or after the response is sent.
Yes, I just detected this during a TeamView session with my partner. On my box my main page ONLY for my site loads once per request.
Then by coincidence while using Fiddler my partner is getting 4 requests to the sample page. It is a 1.5 MB page with big scripts and lotsa other dependencies so this was truly a WTF moment as I have never seen anything like this in 15 years of web development.
If google is doing this I must say they should realize today's sites might have very big pages and very big audiences. That could mean they are jacking bandwidth by a factor of 4 per request. Like I said, WTF?????
I wish this Q&A had a more definitive resolution.
I do use Google Translate widget but this is only occurring on his box and for the main page. The other pages also use the translate widget and I do request my JQUERY via the google CDN. Could anything Google be doing this.

What's with the random Javascript errors?

I'm developing a site in javascript and jquery. Sometimes when I refresh I just get different random errors in firebug. What's the deal?
edit: I'm getting errors like a variable isn't defined, when clearly it is and working, and when i refresh again, the error is gone..
using Firefox V3.5.5 Firebug V.1.5.3 and I'm primarily working with jQuery 1.4.2
OK. While it's more or less impossible to give a reasonable solution to such a general question, I'll just add my 2 cents' worth:
One possible source of "undefined variable" errors comes from including several scripts, which may or may not always load and execute in the same order. If you define a variable in one script (let's call that script declare.js) and use it in another (let's say use.js), and use.js is executed before declare.js, then you will get such an error. If the scripts execute the other way around, everything will appear fine.
If you're interested in this very topic, have a look at e.g. Steve Souders' book Even faster web sites, published by O'Reilly. More specifically, look at the chapter about non-blocking script loading.
Most common cause is that you're trying to execute Javascript before the DOM is loaded and thus before all HTML elements are available in the DOM tree, which in turn may cause that simple calls like document.getElementById(id) and jQuery's $(selector) may return undefined elements. That it sometimes works is pure coincidence and a matter of timing.
You need to ensure that any Javascript/jQuery code which is supposed to be executed during page load and relies on the availability of the elements in the DOM tree, also really get executed after the DOM is loaded. In plain vanilla JS you can do so:
window.onload = function() {
document.getElementById(someId);
}
and in jQuery:
$(document).ready(function() {
$(someSelector);
});

Categories