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

[Float][Fizz][Fiber] support imagesrcset and imagesizes for ReactDOM.preload() #26940

Merged
merged 1 commit into from Jun 15, 2023

Conversation

gnoff
Copy link
Collaborator

@gnoff gnoff commented Jun 13, 2023

For float methods the href argument is usually all we need to uniquely key the request. However when preloading responsive images it is possible that you may need more than one preload for differing imagesizes attributes. When using imagesrcset for preloads the href attribute acts more like a fallback href. For keying purposes the imagesrcset becomes the primary key conceptually.

This change updates the keying logic for ReactDOM.preload() when you pass {as: "image"}

  1. If options.imageSrcSet is a non-emtpy string the key is defined as options.imageSrcSet + options.imageSizes. The href argument is still required but does not participate in keying.
  2. If options.imageSrcSet is empty, missing, or an invalid format the key is defined as the href. Changing the options.imageSizes does not affect the key as this option is inert when not using options.imageSrcSet

Additionally, currently there is a bug in webkit (Safari) that causes preload links to fail to use imageSrcSet and fallback to href even when the browser will correctly resolve srcset on an <img> tag. Because the drawbacks of preloading the wrong image (href over imagesrcset) in a modern browser outweight the drawbacks of not preloading anything for responsive images in browsers that do not support srcset at all we will omit the href attribute whenever options.imageSrcSet is provided. We still require you provide an href since we want to be able to revert this behavior once all major browsers support it

bug link: https://bugs.webkit.org/show_bug.cgi?id=231150

@facebook-github-bot facebook-github-bot added the React Core Team Opened by a member of the React Core Team label Jun 13, 2023
@react-sizebot
Copy link

react-sizebot commented Jun 13, 2023

Comparing: 86acc10...2ac8183

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js +0.19% 164.24 kB 164.56 kB +0.20% 51.73 kB 51.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js +0.18% 171.68 kB 172.00 kB +0.18% 53.97 kB 54.07 kB
facebook-www/ReactDOM-prod.classic.js +0.17% 570.15 kB 571.13 kB +0.18% 100.58 kB 100.75 kB
facebook-www/ReactDOM-prod.modern.js +0.18% 553.93 kB 554.91 kB +0.18% 97.75 kB 97.93 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +0.45% 58.18 kB 58.44 kB +0.55% 17.23 kB 17.32 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +0.45% 58.21 kB 58.47 kB +0.55% 17.25 kB 17.34 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.production.min.js +0.45% 58.35 kB 58.61 kB +0.59% 17.48 kB 17.58 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.production.min.js +0.45% 58.38 kB 58.64 kB +0.59% 17.50 kB 17.61 kB
facebook-www/ReactDOMServer-prod.modern.js +0.44% 135.89 kB 136.49 kB +0.66% 25.24 kB 25.40 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.min.js +0.43% 60.26 kB 60.52 kB +0.52% 18.52 kB 18.62 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.min.js +0.43% 60.28 kB 60.54 kB +0.51% 18.55 kB 18.64 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.production.min.js +0.43% 60.42 kB 60.68 kB +0.53% 18.79 kB 18.89 kB
oss-stable/react-dom/umd/react-dom-server.browser.production.min.js +0.43% 60.45 kB 60.71 kB +0.53% 18.81 kB 18.91 kB
facebook-www/ReactDOMServer-prod.classic.js +0.43% 139.41 kB 140.01 kB +0.67% 25.91 kB 26.09 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.production.min.js +0.43% 60.86 kB 61.12 kB +0.53% 18.66 kB 18.76 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +0.43% 60.69 kB 60.95 kB +0.48% 18.35 kB 18.44 kB
facebook-www/ReactDOMServerStreaming-prod.modern.js +0.42% 142.50 kB 143.10 kB +0.60% 26.90 kB 27.07 kB
oss-experimental/react-dom/cjs/react-dom-static.browser.production.min.js +0.42% 62.12 kB 62.38 kB +0.50% 19.35 kB 19.45 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.min.js +0.42% 62.24 kB 62.50 kB +0.49% 19.41 kB 19.50 kB
oss-experimental/react-dom/umd/react-dom-server.browser.production.min.js +0.42% 62.40 kB 62.66 kB +0.56% 19.65 kB 19.76 kB
oss-experimental/react-dom/cjs/react-dom-static.edge.production.min.js +0.42% 62.45 kB 62.71 kB +0.46% 19.46 kB 19.55 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.production.min.js +0.41% 62.67 kB 62.93 kB +0.52% 18.95 kB 19.05 kB
oss-stable/react-dom/cjs/react-dom-server.bun.production.min.js +0.41% 62.70 kB 62.96 kB +0.52% 18.97 kB 19.07 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.production.min.js +0.41% 62.96 kB 63.22 kB +0.51% 18.79 kB 18.89 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.production.min.js +0.41% 62.99 kB 63.25 kB +0.51% 18.82 kB 18.91 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.production.min.js +0.40% 64.50 kB 64.76 kB +0.48% 19.95 kB 20.04 kB
oss-stable/react-dom/cjs/react-dom-server.edge.production.min.js +0.40% 64.53 kB 64.79 kB +0.49% 19.97 kB 20.07 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.min.js +0.40% 64.62 kB 64.88 kB +0.50% 19.98 kB 20.08 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.min.js +0.40% 64.65 kB 64.91 kB +0.49% 20.00 kB 20.10 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.production.min.js +0.40% 65.30 kB 65.56 kB +0.45% 20.11 kB 20.20 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.production.min.js +0.40% 65.58 kB 65.84 kB +0.47% 19.97 kB 20.07 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.production.min.js +0.39% 66.59 kB 66.85 kB +0.45% 20.87 kB 20.96 kB
oss-experimental/react-dom/cjs/react-dom-static.node.production.min.js +0.39% 66.68 kB 66.94 kB +0.43% 20.92 kB 21.02 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.min.js +0.39% 66.70 kB 66.96 kB +0.44% 20.90 kB 21.00 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.development.js +0.32% 357.55 kB 358.70 kB +0.60% 78.66 kB 79.13 kB
oss-stable/react-dom/cjs/react-dom-server.bun.development.js +0.32% 357.58 kB 358.73 kB +0.60% 78.68 kB 79.16 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.development.js +0.32% 377.37 kB 378.58 kB +0.60% 80.51 kB 80.99 kB
oss-stable/react-dom/umd/react-dom-server.browser.development.js +0.32% 377.40 kB 378.61 kB +0.61% 80.53 kB 81.02 kB
facebook-www/ReactDOMServerStreaming-dev.modern.js +0.32% 366.80 kB 367.98 kB +0.61% 79.44 kB 79.92 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.development.js +0.32% 377.65 kB 378.86 kB +0.61% 80.19 kB 80.68 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.development.js +0.32% 377.68 kB 378.89 kB +0.61% 80.21 kB 80.71 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.development.js +0.32% 360.31 kB 361.46 kB +0.60% 79.56 kB 80.04 kB
oss-stable/react-dom/cjs/react-dom-server.browser.development.js +0.32% 360.33 kB 361.48 kB +0.59% 79.59 kB 80.06 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.32% 360.57 kB 361.72 kB +0.60% 79.26 kB 79.74 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.32% 360.60 kB 361.75 kB +0.60% 79.29 kB 79.77 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.development.js +0.32% 360.72 kB 361.87 kB +0.61% 79.68 kB 80.16 kB
oss-stable/react-dom/cjs/react-dom-server.edge.development.js +0.32% 360.74 kB 361.89 kB +0.61% 79.70 kB 80.19 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.development.js +0.32% 361.80 kB 362.95 kB +0.60% 79.61 kB 80.08 kB
oss-stable/react-dom/cjs/react-dom-server.node.development.js +0.32% 361.83 kB 362.98 kB +0.60% 79.63 kB 80.11 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.development.js +0.32% 362.39 kB 363.54 kB +0.60% 79.72 kB 80.20 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.development.js +0.32% 362.42 kB 363.57 kB +0.60% 79.75 kB 80.23 kB
facebook-www/ReactDOMServer-dev.modern.js +0.32% 371.98 kB 373.16 kB +0.64% 80.69 kB 81.21 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.development.js +0.31% 367.33 kB 368.48 kB +0.59% 80.86 kB 81.34 kB
oss-experimental/react-dom/umd/react-dom-server.browser.development.js +0.31% 386.99 kB 388.20 kB +0.59% 82.72 kB 83.21 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.development.js +0.31% 387.85 kB 389.06 kB +0.59% 82.62 kB 83.11 kB
oss-experimental/react-dom/cjs/react-dom-static.browser.development.js +0.31% 368.81 kB 369.96 kB +0.58% 81.36 kB 81.83 kB
oss-experimental/react-dom/cjs/react-dom-static.edge.development.js +0.31% 369.22 kB 370.37 kB +0.58% 81.47 kB 81.94 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.development.js +0.31% 369.51 kB 370.66 kB +0.58% 81.54 kB 82.01 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.development.js +0.31% 369.92 kB 371.07 kB +0.58% 81.65 kB 82.12 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.31% 370.36 kB 371.51 kB +0.59% 81.46 kB 81.94 kB
oss-experimental/react-dom/cjs/react-dom-static.node.development.js +0.31% 370.97 kB 372.12 kB +0.58% 81.68 kB 82.15 kB
oss-experimental/react-dom/cjs/react-dom-server.node.development.js +0.31% 371.01 kB 372.16 kB +0.58% 81.59 kB 82.06 kB
facebook-www/ReactDOMServer-dev.classic.js +0.31% 379.40 kB 380.58 kB +0.60% 82.35 kB 82.85 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.development.js +0.31% 372.17 kB 373.32 kB +0.59% 81.93 kB 82.41 kB

Generated by 🚫 dangerJS against 2ac8183

@gnoff gnoff force-pushed the preload-imagesrcset branch 3 times, most recently from 8d8bcde to 80a7f09 Compare June 13, 2023 21:03
Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, we're just going to never render "href" when imagesrcset is specified because that will double load in Safari which is worse than missing a preload in very old browsers. However, if Safari fixes that, we'll be able to reenable it so the option will still be there in our API.

@gnoff gnoff force-pushed the preload-imagesrcset branch 3 times, most recently from 0ec641d to f0e6dbd Compare June 15, 2023 21:33
…le cases where srcset and sizes are used over src. Normally we key off an href however in the case of responsive images it is possible that no src attribute is desired. Right now this happens most prominently with Safari which does understand srcset for the img tag but not for the link preload tag. Because of this it can be detrimental to preload with a fallback src since Safari will end up downloading the wrong image 100% of the time.

The solution to this is to allow the user to omit the href if they provide imagesrcset (and optionally) imagesizes. Effectively the key for image preloads will become the union of src (href), imagesrcset, and imagesizes.
@gnoff gnoff merged commit fc929cf into facebook:main Jun 15, 2023
36 checks passed
@gnoff gnoff deleted the preload-imagesrcset branch June 15, 2023 21:50
github-actions bot pushed a commit that referenced this pull request Jun 15, 2023
….preload()` (#26940)

For float methods the href argument is usually all we need to uniquely
key the request. However when preloading responsive images it is
possible that you may need more than one preload for differing
imagesizes attributes. When using imagesrcset for preloads the href
attribute acts more like a fallback href. For keying purposes the
imagesrcset becomes the primary key conceptually.

This change updates the keying logic for `ReactDOM.preload()` when you
pass `{as: "image"}`

1. If `options.imageSrcSet` is a non-emtpy string the key is defined as
`options.imageSrcSet + options.imageSizes`. The `href` argument is still
required but does not participate in keying.
2. If `options.imageSrcSet` is empty, missing, or an invalid format the
key is defined as the `href`. Changing the `options.imageSizes` does not
affect the key as this option is inert when not using
`options.imageSrcSet`

Additionally, currently there is a bug in webkit (Safari) that causes
preload links to fail to use imageSrcSet and fallback to href even when
the browser will correctly resolve srcset on an `<img>` tag. Because the
drawbacks of preloading the wrong image (href over imagesrcset) in a
modern browser outweight the drawbacks of not preloading anything for
responsive images in browsers that do not support srcset at all we will
omit the `href` attribute whenever `options.imageSrcSet` is provided. We
still require you provide an href since we want to be able to revert
this behavior once all major browsers support it

bug link: https://bugs.webkit.org/show_bug.cgi?id=231150

DiffTrain build for [fc929cf](fc929cf)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
….preload()` (facebook#26940)

For float methods the href argument is usually all we need to uniquely
key the request. However when preloading responsive images it is
possible that you may need more than one preload for differing
imagesizes attributes. When using imagesrcset for preloads the href
attribute acts more like a fallback href. For keying purposes the
imagesrcset becomes the primary key conceptually.

This change updates the keying logic for `ReactDOM.preload()` when you
pass `{as: "image"}`

1. If `options.imageSrcSet` is a non-emtpy string the key is defined as
`options.imageSrcSet + options.imageSizes`. The `href` argument is still
required but does not participate in keying.
2. If `options.imageSrcSet` is empty, missing, or an invalid format the
key is defined as the `href`. Changing the `options.imageSizes` does not
affect the key as this option is inert when not using
`options.imageSrcSet`

Additionally, currently there is a bug in webkit (Safari) that causes
preload links to fail to use imageSrcSet and fallback to href even when
the browser will correctly resolve srcset on an `<img>` tag. Because the
drawbacks of preloading the wrong image (href over imagesrcset) in a
modern browser outweight the drawbacks of not preloading anything for
responsive images in browsers that do not support srcset at all we will
omit the `href` attribute whenever `options.imageSrcSet` is provided. We
still require you provide an href since we want to be able to revert
this behavior once all major browsers support it

bug link: https://bugs.webkit.org/show_bug.cgi?id=231150
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
….preload()` (#26940)

For float methods the href argument is usually all we need to uniquely
key the request. However when preloading responsive images it is
possible that you may need more than one preload for differing
imagesizes attributes. When using imagesrcset for preloads the href
attribute acts more like a fallback href. For keying purposes the
imagesrcset becomes the primary key conceptually.

This change updates the keying logic for `ReactDOM.preload()` when you
pass `{as: "image"}`

1. If `options.imageSrcSet` is a non-emtpy string the key is defined as
`options.imageSrcSet + options.imageSizes`. The `href` argument is still
required but does not participate in keying.
2. If `options.imageSrcSet` is empty, missing, or an invalid format the
key is defined as the `href`. Changing the `options.imageSizes` does not
affect the key as this option is inert when not using
`options.imageSrcSet`

Additionally, currently there is a bug in webkit (Safari) that causes
preload links to fail to use imageSrcSet and fallback to href even when
the browser will correctly resolve srcset on an `<img>` tag. Because the
drawbacks of preloading the wrong image (href over imagesrcset) in a
modern browser outweight the drawbacks of not preloading anything for
responsive images in browsers that do not support srcset at all we will
omit the `href` attribute whenever `options.imageSrcSet` is provided. We
still require you provide an href since we want to be able to revert
this behavior once all major browsers support it

bug link: https://bugs.webkit.org/show_bug.cgi?id=231150

DiffTrain build for commit fc929cf.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants