Psysoul

FRONTEND // DIGITAL PAINTING

iOS 6 / 7 Safari (iPhone, iPad) is not loading images when using Server Sent Events (Long-Polling)

| 0 comments

Update: It looks like iOS 8 (or latest Safari) fixes this issue.

If you’re developing something which uses keep-alive connection you might have met with the problem: iOS Safari not loading the images properly (also loading indicator is always shown).

Expected behavior:
Page is being loaded, long-polling connection is started, every image is loaded fine.

Actual behavior:
Page is being loaded, long-polling connection is started, some images are not loaded.

So what is happening in the background?
Browsers limit the maximum connection to any given domain, in case of iOS 6 Safari this limit is 5. There is no problem with the limit itself, as if items (typically scripts and images) are finished downloading, the browser will load the next items. However in case of iOS Safari, the items waiting to be downloaded are not being put in a single queue, but it looks like rather Safari uses the round robin algorithm to determine which resources on which download line (1 to 5) will be downloaded. So if we have 7 resources the 1st and 6th resource will be downloaded on line 1, 2nd and 7th will be downloaded on line 2. The problem is when the first download line is allocated to a keep-alive connection such as a keep-alive connection to the server (Server Sent Events, Long-polling or similar), as the sixth image (or resource) will not be downloaded until the connection is closed, and usually it is not closed for a long time.

Result:
This can cause simple problems: images not loading, or fatal problems: deadlock, if the blocked line would load a javascript.
Same thing could happen with multiple tabs as well.

Reproduce the bug (or feature)
The issue can be easily reproduced by the following link on mobile iOS Safari (Safari on mac has no issue)
iOS Test

Solutions:
There are a couple of solutions to choose from, but not all of them is suitable for every case.

1. Move resources to a subdomain
This might the best solution for the given problem as this solves the problem by avoiding the browser limitation on domains, and it will improve the overall performance as well. Typical implementation is to serve all images / scripts from a subdomain like static.mydomain.com.

2. Defer the script which initializes the keep-alive connection
This might or might not be easy to implement, but if the keep-alive connection is started only after all images have been loaded there should be no problem at all. As per jQuery documentation however (window).load() has multiple caveats, so it is not recommended by itself, however I’ve seen some scripts which might address this problem. Please refer to jQuery docs on load event.
Defer keyword in the script might as well do the trick, however it might not be the proper solution as scripts are usually minified in production environment etc.

3. iOS 8
It looks like iOS 8 Safari has changed the way it is loading resources, so the problem is fixed on iOS 8 devices. At least on an iPad with 8.0.2.

More information:
Apple discussion
Another description.

Author: Psysoul

Psysoul is a front-end developer who is fond of minimal and good quality designs. He also likes to create creative designs, processing sketches, and digital paintings.

Leave a Reply

Required fields are marked *.