Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

animate() in Chrome triggers hundreds of HTTP requests #4968

Open
cfinke opened this issue Nov 9, 2021 · 7 comments
Open

animate() in Chrome triggers hundreds of HTTP requests #4968

cfinke opened this issue Nov 9, 2021 · 7 comments

Comments

@cfinke
Copy link

cfinke commented Nov 9, 2021

Description

Using .animate() on an element with a background image causes Chrome to re-request the background image 60 times per second, but only if:

  • Chrome is in Incognito mode.
  • You refresh the page after the initial pageload.
  • The CSS that sets the background image is in an external CSS file.

The avalanche of requests does not happen on the initial pageload -- only if you reload the page -- and the requests are always served from the in-memory cache of the image, so it's not actually placing load on the Web server, but the behavior seems... bad.

I've only been able to check this behavior in Chrome 95.0.4638.69 on Mac OS 11.6. The example uses jQuery 3.6.0, but I originally noticed it in a project that uses jQuery 2.2.4. Besides jQuery itself, the only JavaScript being run is

jQuery( function ( $ ) {
	$('#animate-me').animate({
	    'width' : '+=100',
	}, 5000, 'linear' );
} );

Link to test case

There is an example here: https://www.chrisfinke.com/files/jquery-animate-bug/

To reproduce:

  1. Open a Chrome Incognito window.
  2. Open the Developer Tools and select the Network tab.
  3. Load the URL https://www.chrisfinke.com/files/jquery-animate-bug/ Note that the 5-second animation completes, and there are a total of four HTTP requests -- the HTML, the stylesheet, jQuery, and the background image (plus the favicon, potentially).
  4. Reload the page by clicking the reload button. Note that this time, there are 300+ requests -- the same four as the original pageload, but an additional 300 requests for the background image.

This behavior persists even if the animation does not visibly affect the element on the page. For example, if instead of changing the width, it increases the font size (when there is no text in the element).

There are a couple of workarounds for anyone who is experiencing this bug in their own code:

  1. Set the background image via an inline style attribute.
  2. Set the background image via a <style> block in the HTML.
@dmethvin
Copy link
Member

dmethvin commented Nov 10, 2021

I'm not seeing this on Chrome 95.0.4638.69 (Official Build) (64-bit) Windows in Icognito. I hit reload and it gives the same number of requests. Do you have any proxies or strange networking setup? For example, a network-based ad blocking proxy.

@aidvu
Copy link

aidvu commented Nov 10, 2021

On Version 95.0.4638.69 (Official Build) (x86_64), here's a screencap:

bug-aval

I hit reload and it gives the same number of requests. Do you have any proxies or strange networking setup?

Try to load w/o cache, then just reload in the middle of animation. That's what did it for me.

@fecore1
Copy link
Contributor

fecore1 commented Nov 11, 2021

On Chrome 95.0.4638.69 Windows, I can reproduce this, and Incognito mode is not necessary.

And the problem may be caused by get bg.png from memory cache.

jquery/src/effects.js

Lines 25 to 35 in 4250b62

function schedule() {
if ( inProgress ) {
if ( document.hidden === false && window.requestAnimationFrame ) {
window.requestAnimationFrame( schedule );
} else {
window.setTimeout( schedule, jQuery.fx.interval );
}
jQuery.fx.tick();
}
}

window.requestAnimationFrame( schedule ); and jQuery.fx.tick(); will be invoked multiple times before the next repaint because inProgress is true until jQuery.fx.stop is invoked.

style[ name ] = value;

In jQuery.fx.tick(); , style['width'] will be set, which will cause the dom repaint, and background-image: url( 'bg.png' ); will get bg.png from memory cache


in my opinion, for the same request ( request bg.png), the browser will try to put all the changes together, execute them all at once. But for memory cache, chrome return image from memory for per request quickly, maybe chrome thinks it's fast from memory and optimization is not necessary.

But I can not find the relevant spec, or someone has a new explanation. .

@cfinke cfinke changed the title animate() in Chrome Incognito window triggers hundreds of HTTP requests animate() in Chrome triggers hundreds of HTTP requests Nov 11, 2021
@cfinke
Copy link
Author

cfinke commented Nov 11, 2021

Confirming that I can now reproduce in a regular window (not incognito) as well.

@jquery jquery deleted a comment Apr 11, 2022
@jquery jquery deleted a comment Apr 11, 2022
@mgol
Copy link
Member

mgol commented Oct 6, 2022

I just returned to this. Is the issue still reproducible? No matter what I try, I don't see it on Chrome 106.0.5249.103 (x86_64) on macOS 12.6 (21G115).

@mgol mgol added the Needs info label Oct 6, 2022
@aidvu
Copy link

aidvu commented Oct 6, 2022

Yep, still reproducible. Check my comment up there.

  • disable cache
  • load it once
  • enable cache
  • just F5 in the middle of the animation

@mgol
Copy link
Member

mgol commented Oct 6, 2022

Your steps didn't work for me but after a few refreshes it suddenly kicked in. Very weird.

In any case, the element stays in the DOM so it's Chrome that triggers the requests, not jQuery code. I don't see how we could bypass it. Maybe it's worth reporting that to the Chromium project at https://crbug.com?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants