Add all deviceSizes to srcset for responsive and fill (#18594)
This commit is contained in:
parent
9569f5a31a
commit
f8c32e556c
3 changed files with 78 additions and 19 deletions
|
@ -105,8 +105,15 @@ function unLazifyImage(lazyImage: HTMLImageElement): void {
|
|||
lazyImage.classList.remove('__lazy')
|
||||
}
|
||||
|
||||
function getDeviceSizes(width: number | undefined): number[] {
|
||||
if (typeof width !== 'number') {
|
||||
function getDeviceSizes(
|
||||
width: number | undefined,
|
||||
layout: LayoutValue
|
||||
): number[] {
|
||||
if (
|
||||
typeof width !== 'number' ||
|
||||
layout === 'fill' ||
|
||||
layout === 'responsive'
|
||||
) {
|
||||
return configDeviceSizes
|
||||
}
|
||||
if (configImageSizes.includes(width)) {
|
||||
|
@ -125,13 +132,14 @@ function getDeviceSizes(width: number | undefined): number[] {
|
|||
function computeSrc(
|
||||
src: string,
|
||||
unoptimized: boolean,
|
||||
layout: LayoutValue,
|
||||
width?: number,
|
||||
quality?: number
|
||||
): string {
|
||||
if (unoptimized) {
|
||||
return src
|
||||
}
|
||||
const widths = getDeviceSizes(width)
|
||||
const widths = getDeviceSizes(width, layout)
|
||||
const largest = widths[widths.length - 1]
|
||||
return callLoader({ src, width: largest, quality })
|
||||
}
|
||||
|
@ -150,6 +158,7 @@ function callLoader(loaderProps: CallLoaderProps) {
|
|||
type SrcSetData = {
|
||||
src: string
|
||||
unoptimized: boolean
|
||||
layout: LayoutValue
|
||||
width?: number
|
||||
quality?: number
|
||||
}
|
||||
|
@ -157,6 +166,7 @@ type SrcSetData = {
|
|||
function generateSrcSet({
|
||||
src,
|
||||
unoptimized,
|
||||
layout,
|
||||
width,
|
||||
quality,
|
||||
}: SrcSetData): string | undefined {
|
||||
|
@ -166,7 +176,7 @@ function generateSrcSet({
|
|||
return undefined
|
||||
}
|
||||
|
||||
return getDeviceSizes(width)
|
||||
return getDeviceSizes(width, layout)
|
||||
.map((w) => `${callLoader({ src, width: w, quality })} ${w}w`)
|
||||
.join(', ')
|
||||
}
|
||||
|
@ -174,6 +184,7 @@ function generateSrcSet({
|
|||
type PreloadData = {
|
||||
src: string
|
||||
unoptimized: boolean
|
||||
layout: LayoutValue
|
||||
width: number | undefined
|
||||
sizes?: string
|
||||
quality?: number
|
||||
|
@ -181,8 +192,9 @@ type PreloadData = {
|
|||
|
||||
function generatePreload({
|
||||
src,
|
||||
width,
|
||||
unoptimized = false,
|
||||
layout,
|
||||
width,
|
||||
sizes,
|
||||
quality,
|
||||
}: PreloadData): ReactElement {
|
||||
|
@ -195,9 +207,15 @@ function generatePreload({
|
|||
<link
|
||||
rel="preload"
|
||||
as="image"
|
||||
href={computeSrc(src, unoptimized, width, quality)}
|
||||
href={computeSrc(src, unoptimized, layout, width, quality)}
|
||||
// @ts-ignore: imagesrcset and imagesizes not yet in the link element type
|
||||
imagesrcset={generateSrcSet({ src, unoptimized, width, quality })}
|
||||
imagesrcset={generateSrcSet({
|
||||
src,
|
||||
unoptimized,
|
||||
layout,
|
||||
width,
|
||||
quality,
|
||||
})}
|
||||
imagesizes={sizes}
|
||||
/>
|
||||
</Head>
|
||||
|
@ -410,11 +428,12 @@ export default function Image({
|
|||
}
|
||||
|
||||
// Generate attribute values
|
||||
const imgSrc = computeSrc(src, unoptimized, widthInt, qualityInt)
|
||||
const imgSrc = computeSrc(src, unoptimized, layout, widthInt, qualityInt)
|
||||
const imgSrcSet = generateSrcSet({
|
||||
src,
|
||||
width: widthInt,
|
||||
unoptimized,
|
||||
layout,
|
||||
width: widthInt,
|
||||
quality: qualityInt,
|
||||
})
|
||||
|
||||
|
@ -458,8 +477,9 @@ export default function Image({
|
|||
{shouldPreload
|
||||
? generatePreload({
|
||||
src,
|
||||
width: widthInt,
|
||||
layout,
|
||||
unoptimized,
|
||||
width: widthInt,
|
||||
sizes,
|
||||
quality: qualityInt,
|
||||
})
|
||||
|
|
|
@ -11,28 +11,28 @@ const Page = () => {
|
|||
width="1200"
|
||||
height="700"
|
||||
layout="responsive"
|
||||
></Image>
|
||||
/>
|
||||
<Image
|
||||
id="responsive2"
|
||||
src="/wide.png"
|
||||
width="1200"
|
||||
height="700"
|
||||
layout="responsive"
|
||||
></Image>
|
||||
/>
|
||||
<Image
|
||||
id="responsive3"
|
||||
src="/wide.png"
|
||||
width="1200"
|
||||
height="700"
|
||||
layout="responsive"
|
||||
></Image>
|
||||
/>
|
||||
<Image
|
||||
id="responsive4"
|
||||
src="/wide.png"
|
||||
width="1200"
|
||||
height="700"
|
||||
layout="responsive"
|
||||
></Image>
|
||||
/>
|
||||
<p>Layout Responsive</p>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -36,15 +36,24 @@ async function hasImageMatchingUrl(browser, url) {
|
|||
}
|
||||
|
||||
async function getComputed(browser, id, prop) {
|
||||
const style = await browser.eval(
|
||||
`getComputedStyle(document.getElementById('${id}')).${prop}`
|
||||
)
|
||||
if (typeof style === 'string') {
|
||||
return parseInt(style.replace(/px$/, ''), 10)
|
||||
const val = await browser.eval(`document.getElementById('${id}').${prop}`)
|
||||
if (typeof val === 'number') {
|
||||
return val
|
||||
}
|
||||
if (typeof val === 'string') {
|
||||
return parseInt(val, 10)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async function getSrc(browser, id) {
|
||||
const src = await browser.elementById(id).getAttribute('src')
|
||||
if (src) {
|
||||
const url = new URL(src)
|
||||
return url.href.slice(url.origin.length)
|
||||
}
|
||||
}
|
||||
|
||||
function getRatio(width, height) {
|
||||
return Math.round((height / width) * 1000)
|
||||
}
|
||||
|
@ -109,6 +118,12 @@ function runTests(mode) {
|
|||
const height = 700
|
||||
const delta = 250
|
||||
const id = 'fixed1'
|
||||
expect(await getSrc(browser, id)).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=1200&q=75'
|
||||
)
|
||||
expect(await browser.elementById(id).getAttribute('srcset')).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=320&q=75 320w, /_next/image?url=%2Fwide.png&w=420&q=75 420w, /_next/image?url=%2Fwide.png&w=768&q=75 768w, /_next/image?url=%2Fwide.png&w=1024&q=75 1024w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w'
|
||||
)
|
||||
await browser.setDimensions({
|
||||
width: width + delta,
|
||||
height: height + delta,
|
||||
|
@ -136,6 +151,12 @@ function runTests(mode) {
|
|||
const height = 700
|
||||
const delta = 250
|
||||
const id = 'intrinsic1'
|
||||
expect(await getSrc(browser, id)).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=1200&q=75'
|
||||
)
|
||||
expect(await browser.elementById(id).getAttribute('srcset')).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=320&q=75 320w, /_next/image?url=%2Fwide.png&w=420&q=75 420w, /_next/image?url=%2Fwide.png&w=768&q=75 768w, /_next/image?url=%2Fwide.png&w=1024&q=75 1024w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w'
|
||||
)
|
||||
await browser.setDimensions({
|
||||
width: width + delta,
|
||||
height: height + delta,
|
||||
|
@ -166,6 +187,12 @@ function runTests(mode) {
|
|||
const height = 700
|
||||
const delta = 250
|
||||
const id = 'responsive1'
|
||||
expect(await getSrc(browser, id)).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=1200&q=75'
|
||||
)
|
||||
expect(await browser.elementById(id).getAttribute('srcset')).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=320&q=75 320w, /_next/image?url=%2Fwide.png&w=420&q=75 420w, /_next/image?url=%2Fwide.png&w=768&q=75 768w, /_next/image?url=%2Fwide.png&w=1024&q=75 1024w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w'
|
||||
)
|
||||
await browser.setDimensions({
|
||||
width: width + delta,
|
||||
height: height + delta,
|
||||
|
@ -196,6 +223,12 @@ function runTests(mode) {
|
|||
const height = 350
|
||||
const delta = 150
|
||||
const id = 'fill1'
|
||||
expect(await getSrc(browser, id)).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=1200&q=75'
|
||||
)
|
||||
expect(await browser.elementById(id).getAttribute('srcset')).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=320&q=75 320w, /_next/image?url=%2Fwide.png&w=420&q=75 420w, /_next/image?url=%2Fwide.png&w=768&q=75 768w, /_next/image?url=%2Fwide.png&w=1024&q=75 1024w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w'
|
||||
)
|
||||
await browser.setDimensions({
|
||||
width: width + delta,
|
||||
height: height + delta,
|
||||
|
@ -226,6 +259,12 @@ function runTests(mode) {
|
|||
const width = await getComputed(browser, id, 'width')
|
||||
const height = await getComputed(browser, id, 'height')
|
||||
await browser.eval(`document.getElementById("${id}").scrollIntoView()`)
|
||||
expect(await getSrc(browser, id)).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=1200&q=75'
|
||||
)
|
||||
expect(await browser.elementById(id).getAttribute('srcset')).toBe(
|
||||
'/_next/image?url=%2Fwide.png&w=320&q=75 320w, /_next/image?url=%2Fwide.png&w=420&q=75 420w, /_next/image?url=%2Fwide.png&w=768&q=75 768w, /_next/image?url=%2Fwide.png&w=1024&q=75 1024w, /_next/image?url=%2Fwide.png&w=1200&q=75 1200w'
|
||||
)
|
||||
expect(await getComputed(browser, id, 'width')).toBe(width)
|
||||
expect(await getComputed(browser, id, 'height')).toBe(height)
|
||||
const delta = 150
|
||||
|
|
Loading…
Reference in a new issue