I have a series of overlapping questions, the intersection of which can best be asked as:

Under what circumstances does an # character (an anchor) in a URL trigger an HTTP fetch, in the context of either an <a href or an <img src ?

Normally, should:

http://foo.com/bar.html#1

and

http://foo.com/bar.html#2

require two different HTTP fetches? I would think the answer should definitely be NO.

More specific details:

The situation that prompted this question was my first attempt to experiment with SVG stacking - a technique where multiple icons can be embedded within a single svg file, so that only a single HTTP request is necessary. Essentially, the idea is that you place multiple SVG icons within a single file, and use CSS to hide all of them, except the one that is selected using a CSS :target selector.

You can then select an individual icon using the # character in the URL when you write the img element in the HTML:

<img 
    src="stacked-icons.svg#icon3" 
    width="80" 
    height="60" 
    alt="SVG Stacked Image" 
/>

When I try this out on Chrome it works perfectly. A single HTTP request is made, and multiple icons can be displayed via the same svg url, using different anchors/targets.

However, when I try this with Firefox (28), I see via the Console that multiple HTTP requests are made - one for each svg URL! So what I see is something like:

GET http://myhost.com/img/stacked-icons.svg#icon1 
GET http://myhost.com/img/stacked-icons.svg#icon2 
GET http://myhost.com/img/stacked-icons.svg#icon3 
GET http://myhost.com/img/stacked-icons.svg#icon4
GET http://myhost.com/img/stacked-icons.svg#icon5

...which of course defeats the purpose of using SVG stacking in the first place.

Is there some reason Firefox is making a separate HTTP request for each URL instead of simply fetching img/stacked-icons.svg once like Chrome does?

This leads into the broader question of - what rules determine whether an # character in the URL should trigger an HTTP request?

Here's a demo in Plunker to help sort out some of these issues

A URI has a couple basic components:

URI

  • Protocol - determines how to send the request
  • Domain - where to send the request
  • Location - file path within the domain
  • Fragment - which part of the document to look in

Media Fragment URI

A fragment is simply identifying a portion of the entire file.

Depending on the implementation of the Media Fragment URI spec, it actually might be totally fair game for the browser to send along the Fragment Identifier. Think about a streaming video, some of which has been cached on the client. If the request is for <code>/video.ogv<b>#t=10,20</b></code> then the server can save space by only sending back the relevant portion/segment/fragment. Moreover, if the applicable portion of the media is already cached on the client, then the browser can prevent a round trip.

Think Round Trips, Not Requests

When a browser issues a GET Request, it does not necessarily mean that it needs to grab a fresh copy of the file all the way from the server. If it has already has a cached version, the request could be answered immediately.

HTTP Status Codes

  • 200 - OK - Got the resource and returned from the server
  • 302 - Found - Found the resource in the cache and not enough has changed since the previous request that we need to get a fresh copy.

Caching Disabled

Various things can affect whether or not a client will perform caching: The way the request was issued (<kbd>F5</kbd> - soft refresh; <kbd>Ctrl</kbd> + <kbd>R</kbd> - hard refresh), the settings on the browser, any development tools that add attributes to requests, and the way the server handles those attributes. Often, when a browser's developer tools are open, it will automatically disable caching so you can easily test changes to files. If you're trying to observe caching behavior specifically, make sure you don't have any developer settings that are interfering with this.

When comparing requests across browsers, to help mitigate the differences between Developer Tool UI's, you should use a tool like fiddler to inspect the actual HTTP requests and responses that go out over the wire. I'll show you both for the simple plunker example. When the page loads it should request two different ids in the same stacked svg file.

Here are side by side requests of the same test page in Chrome 39, FF 34, and IE 11:

Fiddler - Disable Caching
Dev Tools - Disable Caching

Caching Enabled

But we want to test what would happen on a normal client where caching is enabled. To do this, update your dev tools for each browser, or go to fiddler and Rules > Performance > and uncheck Disable Caching.

Now our request should look like this:

Fiddler - Enable Caching Dev Tools - Enable Caching

Now all the files are returned from the local cache, regardless of fragment ID

The developer tools for a particular browser might try to display the fragment id for your own benefit, but fiddler should always display the most accurate address that is actually requested. Every browser I tested omitted the fragment part of the address from the request:

HTTP Request

Bundling Requests

Interestingly, chrome seems to be smart enough to prevent a second request for the same resource, but FF and IE fail to do so when a fragment is part of address. This is equally true for SVG's and PNG's. Consequently, the first time a page is ever requested, the browser will load one file for each time the SVG stack is actually used. Thereafter, it's happy to take the version from the cache, but will hurt performance for new viewers.

Final Score

CON: First Trip - SVG Stacks are not fully supported in all browsers. One request made per instance.
PRO: Second Trip - SVG resources will be cached appropriately

Additional Resources

Bugs

Typically, identical resources that are requested for a page will be bundled into a single request that will satisfy all requesting elements. Chrome appears to have already fixed this, but I've opened bugs for FF and IE to one day fix this.