Bug 66474 - Dynamically injected base tag from external script causes extra requests
: Dynamically injected base tag from external script causes extra requests
Status: RESOLVED WONTFIX
: WebKit
Page Loading
: 528+ (Nightly build)
: Macintosh Intel Mac OS X 10.7
: P2 Normal
Assigned To:
: http://jsbin.com/umulij/8
:
:
:
  Show dependency treegraph
 
Reported: 2011-08-18 09:41 PST by
Modified: 2011-08-19 06:25 PST (History)


Attachments


Note

You need to log in before you can comment on or make changes to this bug.


Description From 2011-08-18 09:41:38 PST
When referencing an external script that dynamically injects a base tag with a new base href, the browser downloads subsequent assets twice each: once with a path that respects the base href, then again with a path that does not. This problem is only true in externally-referenced scripts; inline scripts work as expected, causing one request that is routed through the base href.

Steps to reproduce:

1. open http://jsbin.com/umulij/8 in Chrome (currently running version 13.0.782.112)
2. Inspect the resources panel and notice two requests to the image referenced in the body

Note that the image references are not real, so the 404s are expected.

You can view the source for this demo here:
http://jsbin.com/umulij/8/edit

The  referenced JavaScript file simply creates a base element with a faux href and injects it as a first child of the head element:
http://filamentgroup.com/examples/rwdtemp/test.js

Note that when this same script is inline in the head of the document, only one request is made. This is the intended behavior.
http://jsbin.com/ucunip/5 (source can be viewed here: http://jsbin.com/ucunip/5/edit )

As an aside, this bug now also exists in Firefox 6. Previously, this was not the behavior in either browser.
------- Comment #1 From 2011-08-18 12:07:59 PST -------
I wonder if these are preloaded generated requests that are being carried on.
------- Comment #2 From 2011-08-18 13:40:58 PST -------
Pretty sure they are. This is not a reasonable thing to do. -> wontfix
------- Comment #3 From 2011-08-18 20:21:45 PST -------
(In reply to comment #2)
> Pretty sure they are. This is not a reasonable thing to do. -> wontfix

I'd really appreciate if this issue could be given a little more consideration. Injecting and/or modifying and existing base element via JavaScript is useful for a number of reasons. 

For one, modifying the base href is a reliable way to ensure assets that are requested via ajax-appended markup are routed through the relative URL they come from (for example, when appended HTML contains scripts, styles, images, etc). We modify the base element constantly in the jQuery Mobile framework as new pages are brought in via Ajax. I can test to see if this change has any effect there currently, as I'm not sure if it does.

The case I was concerned with in particular was that the "Responsive Images" technique, which is one of only a few ways to currently route images appropriately based on screen resolution in responsive designs, no longer works because of this recent change. While this can be done other ways, the base tag approach can be the most useful depending on the site. (more here: http://filamentgroup.com/lab/responsive_images_experimenting_with_context_aware_image_sizing/ )


That said, I think the part that needs clarification most here is why this technique works perfectly when the script is inline in the head, but not when it's referenced externally. Shouldn't these two scenarios behave the same?

I've noticed that an externally referenced script is able to set a cookie that is subsequently carried by the image request, so the problem does not appear to be related to timing. In fact, looking at the profiler, the request to the non-base-href image src goes out AFTER the one that is routed properly. This seems to suggest a bug, rather than an optimized prefetch.

I ask that you reconsider this bug, as it doesn't appear to match expected behavior.
Thanks so much
------- Comment #4 From 2011-08-18 21:16:36 PST -------
> That said, I think the part that needs clarification most here is why this technique works perfectly when the script is inline in the head, but not when it's referenced externally. Shouldn't these two scenarios behave the same?

Sounds like the difference is that the browser knows immediately during parsing the contents of inline script blocks, so it can abandon an invalidated resource preload right away if a base tag is injected. For an external script resource, the base tag injection may/will happen "later", when the script finishes loading and executes, which is likely well after the other resource loading has already started. Aborting a request/response in mid flight is probably harder to do, and also probably doesn't really save much in bandwidth on either side of the fence.
------- Comment #5 From 2011-08-18 21:30:20 PST -------
Thanks, Kyle. 

That's a helpful theory, but it's interesting that a cookie set within an external is successfully carried with both image requests. That seems to suggest that the script is executed before these requests go out, as I'd expect, but for some reason the base tag situation is different.

Here's a demo showing image requests carrying cookies from that JS file: 
http://jsbin.com/ifupav/2 (src: http://jsbin.com/ifupav/2/edit )
------- Comment #6 From 2011-08-19 06:25:47 PST -------
Inserting base element effectively changes all the subsequent URLs on the page. Any script may insert one so to avoid double loads we could never load anything else as long as there is a pending script load. This would mean disabling preloading, which is out of the question.

Only reasonable fix would be to ignore the base url change for elements for which we have already started loads for (HTML5 text could be interpreted like that). However that could break something and is probably not worth the effort in any case.