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

Bug: <img> within a <picture> is being requested twice in Firefox #20682

Closed
cherouvim opened this issue Jan 28, 2021 · 14 comments
Closed

Bug: <img> within a <picture> is being requested twice in Firefox #20682

cherouvim opened this issue Jan 28, 2021 · 14 comments
Labels
Component: DOM Resolution: Stale Automatically closed due to inactivity Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@cherouvim
Copy link

cherouvim commented Jan 28, 2021

When I have an <img> within a <picture> element, e.g for implementing responsive images, then Firefox requests that image file twice. Some of the times the first request to the image will stop with an NS_BINDING_ABORTED, it'll always return receive 0 bytes, and the server will log a 499 response (client closed request) or a 200. Removing the <picture> element and simply leaving <img> in the JSX, solves the problem, but of course I do need the <picture>. This happens in Firefox 84 and 85 (private mode, no extensions), and does not happen in Chrome.

An important detail is that this only happens when rendering through react, either in dev mode or build mode (in create-react-app). If I save the generated HTML and render it without any JavaScript, then the double request never happens again.

React version: 17.0.1 (happens in 16 too)

JS:

import React from "react";
import ReactDOM from "react-dom";
ReactDOM.render(
  <picture>
    <img src="https://via.placeholder.com/300x300?text=JPG" alt="JPG" width="300" height="300" />
  </picture>,
  window.document.getElementById("root")
);

HTML:

<!doctype html>
<html>
  <body>
    <div id="root"></div>
  </body>
</html>

Live example: https://luues.csb.app/

Result screenshot of network tab:
<image> within a <picture> is being requested twice in Firefox

In case it helps, note that in the following example, the first (broken) request will be for the jpg image, and then another for the correct webp one:

<picture>
    <source srcSet="https://via.placeholder.com/300x300?text=WEBP" type="image/webp" />
    <img src="https://via.placeholder.com/300x300?text=JPG" alt="JPG" width="300" height="300" />
</picture>
@cherouvim cherouvim added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Jan 28, 2021
@cherouvim cherouvim changed the title Bug: <image> within a <picture> is being requested twice in Firefox Bug: <img> within a <picture> is being requested twice in Firefox Jan 29, 2021
@sunknudsen
Copy link

sunknudsen commented Feb 5, 2021

Hey @cherouvim,

I am experiencing a similar issue where in dev mode (CRA / npm start), both the <img src> and <source srcSet> images are loaded in Firefox (failover loads first).

This issue is gone when I run npm run build and serve my app using Express.

In your example, have you noticed if the WebP image is loaded vs the failover?

@cherouvim
Copy link
Author

@sunknudsen the failover .jpg is being requested and partially fetched, and the .webp is fully loaded and eventually displayed.

@sunknudsen
Copy link

sunknudsen commented Feb 6, 2021

Hey guys,

I was able to reproduce this issue with very little code added to a clean-install (npx create-react-app my-app --template typescript) of Create React App.

I created a repo that can be used to debug this issue (please git checkout react-picture-issue).

I also included a pre-rendered no-js file (see https://github.com/sunknudsen/my-app/blob/react-picture-issue/public/index-rendered-no-js.html) that confirms the issue is only present when the React JavaScript code is running.

To use my-app to reproduce the issue, please run the following:

$ git clone https://github.com/sunknudsen/my-app.git

$ cd my-app

$ git checkout react-picture-issue

$ npm install

$ npm start

To test React version, go to http://localhost:3000/ in Firefox and open developer tools at the network tab (notice the request to http://localhost:3000/static/media/test-1920x1080.png?).

React

To test no-js version, go to http://localhost:3000/index-rendered-no-js.html in Firefox and open developer tools at the network tab (notice how the request to http://localhost:3000/static/media/test-1920x1080.png is not present?).

no-js

I am still unsure if this is a Firefox issue or a React issue. Perhaps someone from the core React team (@bvaughn?) can help us figure this one out?

@cherouvim
Copy link
Author

cherouvim commented Feb 15, 2021

In addition, problem is not reproducible with vanilla JS:

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
        <script>
            document.getElementById('root').innerHTML =
                '<picture><img src="https://via.placeholder.com/300x300?text=JPG" alt="JPG" width="300" height="300" /></picture>';
        </script>
    </body>
</html>

@cherouvim
Copy link
Author

This issue appears first on 0.15.0-alpha.1. I cannot reproduce it on anything below that (e.g 0.14.10).

Live demo (use Firefox, open Dev Tools on Network tab):

@cherouvim
Copy link
Author

cherouvim commented Feb 15, 2021

Also reproducible without JSX:

<!DOCTYPE html>
    <head>
        <!-- 14.2 does not reproduce the issue -->
        <!-- <script src="https://unpkg.com/react@0.14.2/dist/react.js" crossorigin></script> -->
        <!-- <script src="https://unpkg.com/react-dom@0.14.2/dist/react-dom.js" crossorigin></script> -->

        <!-- 15, 16, and 17 does reproduce the issue -->
        <script src="https://unpkg.com/react@17.0.1/umd/react.production.min.js" crossorigin></script>
        <script src="https://unpkg.com/react-dom@17.0.1/umd/react-dom.production.min.js" crossorigin></script>
    </head>
    <body>
        <div id="root"></div>
        <script>
            ReactDOM.render(
                React.createElement(
                    "picture",
                    {},
                    React.createElement(
                        "img",
                        {
                            src: "https://via.placeholder.com/300x300?text=JPG",
                            alt: "JPG"
                        },
                        undefined
                    )
                ),
                window.document.getElementById("root")
            );
        </script>
    </body>
</html>

@stale
Copy link

stale bot commented Jan 8, 2022

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Jan 8, 2022
@markolucky7
Copy link

Bump

@stale stale bot removed the Resolution: Stale Automatically closed due to inactivity label Mar 10, 2022
@simeyla
Copy link

simeyla commented May 28, 2022

Here's why

Even in Chrome when you execute the following it will IMMEDIATELY request the image:

 const img = new Image();
 img.src = 'https://placeimg.com/640/480/any';

You don't need to add it to the DOM. So clearly when React creates the DOM it does something like this at some point. It looks like Safari may be even more eager to start the load than Chrome.

The solution is to append the img tag inside the picture tag BEFORE setting src on the img tag. That prevents the img tag from being treated as its own thing (verified in Angular).

I'm afraid I don't have a React solution for how to accomplish this since I only know Angular, but hopefully that helps explain the reason. It's just the way the Image() object works.

See also #22684

@sutarmin
Copy link

The explanation about the eager fetching of Image makes perfect sense. Simple React workaround that did the job for me:

function addSrc(src: string) {
	return function (img: HTMLImageElement) {
		if (img) {
			img.src = src;
		}
	};
}

...

<img ref={addSrc(imgUrl)} />

@mihanizm56
Copy link

any updates?)
this problem still exists

@philipatkinson
Copy link

In the absence of a Webkit fix to bring it in line with how Chromium handles the situation, one (slightly ugly) solution to this is not define a src on the fallback image tag. This is obviously a problem if either the browser doesn't support the picture tag (increasingly rare), or if you fail to include a source image type that Webkit does not support.

Copy link

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Apr 10, 2024
Copy link

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: DOM Resolution: Stale Automatically closed due to inactivity Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

8 participants