bf4 / controljs

Automatically exported from code.google.com/p/controljs
Apache License 2.0
0 stars 0 forks source link

Scripts with missing or near-term cache-control headers requested twice #10

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Originally discussed <a 
href=http://groups.google.com/group/controljs/browse_thread/thread/aa4f4885827c1
d31/61e1387b3a1e20fd#61e1387b3a1e20fd>on this thread</a>. 

What steps will reproduce the problem?
1. Load a script using ControlJS which delivers a no-cache cache-control header 
value. An example would be any ad server
2. You can configure Fiddler's AutoResponder to send no-cache headers.  

What is the expected output? What do you see instead?

ControlJS uses an Image or Object element to pre-fetch the URL, but has to 
create an actual Script element to execute it.  When the URL cannot be cached, 
it will be re-requested.  

In the attached screenshot, Multiples.jpg, Fiddler was configured with an 
auto-responder to send a Cache-control: no-cache header.  You can see how 
jQuery is requested twice. 

The spec is evolving so ControlJS' pre-fetching behavior will be supported 
natively (discussed <a 
href=http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order>here</a> ).  
Until that time, this ccan be fixed in Internet Explorer using the 
readystatechange event.  

IE will download any resource as soon as its SRC attribute is set and update 
its readyState property to "loaded" once the resource has been downloaded; 
however, script element will **not execute** until it is inserted into the DOM. 
 This is analogous to how all browsers implement dynamically created images: 
the image is fetched when the src attribute is set, but is not displayed until 
the element is added to the DOM.  

ControlJS can use this to replace its current pre-fetching mechanism in IE and 
eliminate the possibility scripts will be requested multiple times.  

Please provide any additional information below.

The attached patch implements this in ControlJS.  Instead of using an IMG to 
pre-fetch, it creates an actual script element.  Once the script's readyState 
property moves to "loaded", the code stores the actual script element in the 
CJS.hLoaded object.  This is done in the CJS.downloadScriptPrefetch method.  

In the CJS.execScript, a check is added to see if the value for 
CJS.hLoaded[src] is a SCRIPT element.  It then inserts this script element into 
the DOM instead of creating a new one.  This prevents double-retrieval of 
un-cacheable URLs and still maintains the on-demand execution pattern.  

The screenshot Singular.jpg shows the effect of this patch.  

Original issue reported on code.google.com by serverhe...@gmail.com on 17 Dec 2010 at 1:09

Attachments:

GoogleCodeExporter commented 9 years ago
It might be esp. valuable to do this for IE. 

In menu.php the two scripts (jquery.min.js and fg.menu.js) get loaded twice - 
first as images and then as scripts. The intention is that the 2nd pass (as 
scripts) would be read from cache. But when I run the example multiple times 
one or both of the scripts frequently get re-requested and generate a 200 
response - so they're downloaded twice. 

I believe this is due to quirky caching behavior in IE - if you have a Vary 
header and no ETag then IE is flaky about caching. In this case those scripts 
have a Vary header and no ETag (or at least a blank ETag).

Therefore, it's more likely that the current technique (load as image then load 
as script) will cause double downloads in IE. If instead we move to this new 
approach where the file is only requested once, the issue is avoided.

Original comment by stevesou...@gmail.com on 17 Dec 2010 at 1:29

GoogleCodeExporter commented 9 years ago
It should be noted that this will work only in IE -- the other browsers either 
do not begin to download the script until it's inserted (Opera) or don't 
provide the readystatechange event.

IMO, this seems to be an elegant means by which dynamic scripts can be managed. 
 The recommendation of a noted wpo expert to the w3c to include readystate 
notification in the HTML 5 specification would carry considerable weight.  

Original comment by serverhe...@gmail.com on 17 Dec 2010 at 6:08

GoogleCodeExporter commented 9 years ago
Attached patch contains two fixes: 1) undefined variables in non-IE browsers 
and 2) resolution to the problem of aborted connections due to premature GC.  

Demonstration of #2: http://digital-fulcrum.com/webperf/ieabort/fail/

Original comment by serverhe...@gmail.com on 23 Dec 2010 at 8:05

Attachments:

GoogleCodeExporter commented 9 years ago
Step 12 in the HTML5 specification 
(http://www.w3.org/TR/html5/scripting-1.html#running-a-script) suggests the 
following: 
"For performance reasons, user agents may start fetching the script as soon as 
the attribute is set, instead, in the hope that the element will be inserted 
into the document."

In Browsers that implement this suggestion (currently only IE) pre-fetching can 
be accomplished simply by creating the script and assigning its src attribute 
-- when execution is desired, the script can be inserted into the document.  
This patch waits until the script element transitions to the "loaded" state 
before it will be inserted and is overly complex and relies on a  non-standard 
property and event.  

It probably makes more sense to use the specification's suggestion as the 
*core* of the pre-fetching.  I personally believe we should make the 
non-conforming browser vendors aware of this suggestion in the spec.  Should 
they choose NOT to implement it, does it make sense for ControlJS to 
consciously *subvert* their decision?  

Original comment by serverhe...@gmail.com on 27 Dec 2010 at 7:09