fix(next/image): undo tight coupling between priority=true and fetchPriority=high (#67351)

## History

When we added `priority` prop to `next/image`, there was no
`fetchPriority` so we instead used this to preload the image in the
head.

Then when browsers added support `fetchPriority`, we automatically added
`fetchPriority=high` when `priority={true}` to signal to the browser
that this was a high priority image. This priority is added to the img
and the preload.

However, we saw cases where images are blocking critical css. Per
@gnoff:

> React currently prioritizes font preloads then high priority images,
then css in the initial page load

Due to these changes in React (aka Float), we should no longer set
`fetchPriority=high`, although the user can still manually add that prop
if needed.
This commit is contained in:
Steven 2024-07-01 14:42:42 -04:00 committed by GitHub
parent ef83433c3e
commit 73b552a9a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 45 additions and 23 deletions

View file

@ -400,9 +400,6 @@ export function getImgProps(
// through the built-in Image Optimization API.
unoptimized = true
}
if (priority) {
fetchPriority = 'high'
}
const qualityInt = getInt(quality)

View file

@ -143,7 +143,7 @@ function runTests(mode) {
'/_next/image?url=%2Ftest.webp&w=640&q=75 1x, /_next/image?url=%2Ftest.webp&w=828&q=75 2x'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '',
imagesrcset:
'/_next/image?url=%2Ftest.webp&w=640&q=75 1x, /_next/image?url=%2Ftest.webp&w=828&q=75 2x',
@ -158,7 +158,7 @@ function runTests(mode) {
'/_next/image?url=%2Fwide.png&w=640&q=75 640w, /_next/image?url=%2Fwide.png&w=750&q=75 750w, /_next/image?url=%2Fwide.png&w=828&q=75 828w, /_next/image?url=%2Fwide.png&w=1080&q=75 1080w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w, /_next/image?url=%2Fwide.png&w=1920&q=75 1920w, /_next/image?url=%2Fwide.png&w=2048&q=75 2048w, /_next/image?url=%2Fwide.png&w=3840&q=75 3840w'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '100vw',
imagesrcset:
'/_next/image?url=%2Fwide.png&w=640&q=75 640w, /_next/image?url=%2Fwide.png&w=750&q=75 750w, /_next/image?url=%2Fwide.png&w=828&q=75 828w, /_next/image?url=%2Fwide.png&w=1080&q=75 1080w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w, /_next/image?url=%2Fwide.png&w=1920&q=75 1920w, /_next/image?url=%2Fwide.png&w=2048&q=75 2048w, /_next/image?url=%2Fwide.png&w=3840&q=75 3840w',
@ -173,7 +173,7 @@ function runTests(mode) {
'/_next/image?url=%2Ftest.png&w=640&q=75 1x, /_next/image?url=%2Ftest.png&w=828&q=75 2x'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '',
imagesrcset:
'/_next/image?url=%2Ftest.png&w=640&q=75 1x, /_next/image?url=%2Ftest.png&w=828&q=75 2x',
@ -188,7 +188,7 @@ function runTests(mode) {
'/_next/image?url=%2Ftest.tiff&w=640&q=75 1x, /_next/image?url=%2Ftest.tiff&w=828&q=75 2x'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '',
imagesrcset:
'/_next/image?url=%2Ftest.tiff&w=640&q=75 1x, /_next/image?url=%2Ftest.tiff&w=828&q=75 2x',
@ -210,19 +210,19 @@ function runTests(mode) {
await browser.elementById('responsive2').getAttribute('loading')
).toBe(null)
// When priority={true}, we should set fetchpriority="high"
// When priority={true}, we should not set fetchpriority="high"
expect(
await browser.elementById('basic-image').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
expect(
await browser.elementById('load-eager').getAttribute('fetchpriority')
).toBe(null)
expect(
await browser.elementById('responsive1').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
expect(
await browser.elementById('responsive2').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
// Setting fetchPriority="low" directly should pass-through to <img>
expect(
@ -234,7 +234,7 @@ function runTests(mode) {
expect(
await browser.elementById('belowthefold').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
expect(
await browser.elementById('belowthefold').getAttribute('loading')
).toBe(null)
@ -860,7 +860,7 @@ function runTests(mode) {
expect(await img.getAttribute('alt')).toBe('Hero')
expect(await img.getAttribute('width')).toBe('400')
expect(await img.getAttribute('height')).toBe('400')
expect(await img.getAttribute('fetchPriority')).toBe('high')
expect(await img.getAttribute('fetchPriority')).toBeNull()
expect(await img.getAttribute('sizes')).toBeNull()
expect(await img.getAttribute('src')).toBe(
'/_next/image?url=%2Ftest_light.png&w=828&q=75'

View file

@ -144,7 +144,7 @@ function runTests(mode) {
'/_next/image?url=%2Ftest.webp&w=640&q=75 1x, /_next/image?url=%2Ftest.webp&w=828&q=75 2x'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '',
imagesrcset:
'/_next/image?url=%2Ftest.webp&w=640&q=75 1x, /_next/image?url=%2Ftest.webp&w=828&q=75 2x',
@ -159,7 +159,7 @@ function runTests(mode) {
'/_next/image?url=%2Fwide.png&w=640&q=75 640w, /_next/image?url=%2Fwide.png&w=750&q=75 750w, /_next/image?url=%2Fwide.png&w=828&q=75 828w, /_next/image?url=%2Fwide.png&w=1080&q=75 1080w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w, /_next/image?url=%2Fwide.png&w=1920&q=75 1920w, /_next/image?url=%2Fwide.png&w=2048&q=75 2048w, /_next/image?url=%2Fwide.png&w=3840&q=75 3840w'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '100vw',
imagesrcset:
'/_next/image?url=%2Fwide.png&w=640&q=75 640w, /_next/image?url=%2Fwide.png&w=750&q=75 750w, /_next/image?url=%2Fwide.png&w=828&q=75 828w, /_next/image?url=%2Fwide.png&w=1080&q=75 1080w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w, /_next/image?url=%2Fwide.png&w=1920&q=75 1920w, /_next/image?url=%2Fwide.png&w=2048&q=75 2048w, /_next/image?url=%2Fwide.png&w=3840&q=75 3840w',
@ -174,7 +174,7 @@ function runTests(mode) {
'/_next/image?url=%2Ftest.png&w=640&q=75 1x, /_next/image?url=%2Ftest.png&w=828&q=75 2x'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '',
imagesrcset:
'/_next/image?url=%2Ftest.png&w=640&q=75 1x, /_next/image?url=%2Ftest.png&w=828&q=75 2x',
@ -189,7 +189,7 @@ function runTests(mode) {
'/_next/image?url=%2Ftest.tiff&w=640&q=75 1x, /_next/image?url=%2Ftest.tiff&w=828&q=75 2x'
)
).toEqual({
fetchpriority: 'high',
fetchpriority: '',
imagesizes: '',
imagesrcset:
'/_next/image?url=%2Ftest.tiff&w=640&q=75 1x, /_next/image?url=%2Ftest.tiff&w=828&q=75 2x',
@ -211,19 +211,19 @@ function runTests(mode) {
await browser.elementById('responsive2').getAttribute('loading')
).toBe(null)
// When priority={true}, we should set fetchpriority="high"
// When priority={true}, we not should set fetchpriority="high"
expect(
await browser.elementById('basic-image').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
expect(
await browser.elementById('load-eager').getAttribute('fetchpriority')
).toBe(null)
expect(
await browser.elementById('responsive1').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
expect(
await browser.elementById('responsive2').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
// Setting fetchPriority="low" directly should pass-through to <img>
expect(
@ -235,7 +235,7 @@ function runTests(mode) {
expect(
await browser.elementById('belowthefold').getAttribute('fetchpriority')
).toBe('high')
).toBe(null)
expect(
await browser.elementById('belowthefold').getAttribute('loading')
).toBe(null)
@ -861,7 +861,7 @@ function runTests(mode) {
expect(await img.getAttribute('alt')).toBe('Hero')
expect(await img.getAttribute('width')).toBe('400')
expect(await img.getAttribute('height')).toBe('400')
expect(await img.getAttribute('fetchPriority')).toBe('high')
expect(await img.getAttribute('fetchPriority')).toBeNull()
expect(await img.getAttribute('sizes')).toBeNull()
expect(await img.getAttribute('src')).toBe(
'/_next/image?url=%2Ftest_light.png&w=828&q=75'

View file

@ -50,6 +50,31 @@ describe('getImageProps()', () => {
expect(Object.entries(props)).toStrictEqual([
['alt', 'a nice desc'],
['id', 'my-image'],
['width', 100],
['height', 200],
['decoding', 'async'],
['style', { color: 'transparent' }],
[
'srcSet',
'/_next/image?url=%2Ftest.png&w=128&q=75 1x, /_next/image?url=%2Ftest.png&w=256&q=75 2x',
],
['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
])
})
it('should handle fetchPriority', async () => {
const { props } = getImageProps({
alt: 'a nice desc',
id: 'my-image',
src: '/test.png',
width: 100,
height: 200,
fetchPriority: 'high',
})
expect(warningMessages).toStrictEqual([])
expect(Object.entries(props)).toStrictEqual([
['alt', 'a nice desc'],
['id', 'my-image'],
['loading', 'lazy'],
['fetchPriority', 'high'],
['width', 100],
['height', 200],