Skip to content

Commit

Permalink
Merge branch 'canary' into streaming-path-rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] committed Feb 18, 2022
2 parents 462d867 + a4f5463 commit d87a7c8
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 20 deletions.
10 changes: 7 additions & 3 deletions examples/with-tailwindcss/pages/index.tsx
@@ -1,6 +1,8 @@
import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'

export default function Home() {
const Home: NextPage = () => {
return (
<div className="flex min-h-screen flex-col items-center justify-center py-2">
<Head>
Expand Down Expand Up @@ -68,15 +70,17 @@ export default function Home() {

<footer className="flex h-24 w-full items-center justify-center border-t">
<a
className="flex items-center justify-center"
className="flex items-center justify-center gap-2"
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<img src="/vercel.svg" alt="Vercel Logo" className="ml-2 h-4" />
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</a>
</footer>
</div>
)
}

export default Home
5 changes: 1 addition & 4 deletions packages/create-next-app/templates/default/gitignore
Expand Up @@ -26,10 +26,7 @@ yarn-error.log*
.pnpm-debug.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
.env*.local

# vercel
.vercel
5 changes: 1 addition & 4 deletions packages/create-next-app/templates/typescript/gitignore
Expand Up @@ -26,10 +26,7 @@ yarn-error.log*
.pnpm-debug.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
.env*.local

# vercel
.vercel
Expand Down
29 changes: 20 additions & 9 deletions packages/next/client/image.tsx
Expand Up @@ -23,6 +23,17 @@ if (typeof window === 'undefined') {
;(global as any).__NEXT_IMAGE_IMPORTED = true
}

let warnOnce = (_: string) => {}
if (process.env.NODE_ENV !== 'production') {
const warnings = new Set<string>()
warnOnce = (msg: string) => {
if (!warnings.has(msg)) {
console.warn(msg)
}
warnings.add(msg)
}
}

const VALID_LOADING_VALUES = ['lazy', 'eager', undefined] as const
type LoadingValue = typeof VALID_LOADING_VALUES[number]
type ImageConfig = ImageConfigComplete & { allSizes: number[] }
Expand Down Expand Up @@ -274,7 +285,7 @@ function handleLoading(
if (!parent.position) {
// The parent has not been rendered to the dom yet and therefore it has no position. Skip the warnings for such cases.
} else if (layout === 'responsive' && parent.display === 'flex') {
console.warn(
warnOnce(
`Image with src "${src}" may not render properly as a child of a flex container. Consider wrapping the image with a div to configure the width.`
)
} else if (
Expand All @@ -283,7 +294,7 @@ function handleLoading(
parent.position !== 'fixed' &&
parent.position !== 'absolute'
) {
console.warn(
warnOnce(
`Image with src "${src}" may not render properly with a parent using position:"${parent.position}". Consider changing the parent style to position:"relative" with a width and height.`
)
}
Expand Down Expand Up @@ -410,7 +421,7 @@ export default function Image({
)
}
if (layout === 'fill' && (width || height)) {
console.warn(
warnOnce(
`Image with src "${src}" and "layout='fill'" has unused properties assigned. Please remove "width" and "height".`
)
}
Expand All @@ -427,13 +438,13 @@ export default function Image({
)
}
if (sizes && layout !== 'fill' && layout !== 'responsive') {
console.warn(
warnOnce(
`Image with src "${src}" has "sizes" property but it will be ignored. Only use "sizes" with "layout='fill'" or "layout='responsive'".`
)
}
if (placeholder === 'blur') {
if (layout !== 'fill' && (widthInt || 0) * (heightInt || 0) < 1600) {
console.warn(
warnOnce(
`Image with src "${src}" is smaller than 40x40. Consider removing the "placeholder='blur'" property to improve performance.`
)
}
Expand All @@ -453,12 +464,12 @@ export default function Image({
}
}
if ('ref' in rest) {
console.warn(
warnOnce(
`Image with src "${src}" is using unsupported "ref" property. Consider using the "onLoadingComplete" property instead.`
)
}
if ('style' in rest) {
console.warn(
warnOnce(
`Image with src "${src}" is using unsupported "style" property. Please use the "className" property instead.`
)
}
Expand All @@ -475,7 +486,7 @@ export default function Image({
url = new URL(urlStr)
} catch (err) {}
if (urlStr === src || (url && url.pathname === src && !url.search)) {
console.warn(
warnOnce(
`Image with src "${src}" has a "loader" property that does not implement width. Please implement it or use the "unoptimized" property instead.` +
`\nRead more: https://nextjs.org/docs/messages/next-image-missing-loader-width`
)
Expand All @@ -500,7 +511,7 @@ export default function Image({
!lcpImage.src.startsWith('blob:')
) {
// https://web.dev/lcp/#measure-lcp-in-javascript
console.warn(
warnOnce(
`Image with src "${lcpImage.src}" was detected as the Largest Contentful Paint (LCP). Please add the "priority" property if this image is above the fold.` +
`\nRead more: https://nextjs.org/docs/api-reference/next/image#priority`
)
Expand Down
23 changes: 23 additions & 0 deletions test/integration/image-component/default/pages/warning-once.js
@@ -0,0 +1,23 @@
import React from 'react'
import Image from 'next/image'

const Page = () => {
const [count, setCount] = React.useState(0)
return (
<>
<h1>Warning should print at most once</h1>
<Image
id="w"
layout="fixed"
src="/test.png"
width="400"
height="400"
sizes="50vw"
/>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<footer>footer here</footer>
</>
)
}

export default Page
30 changes: 30 additions & 0 deletions test/integration/image-component/default/test/index.test.js
Expand Up @@ -812,6 +812,36 @@ function runTests(mode) {
await browser.elementById('without-loader').getAttribute('srcset')
).toBe('/test.svg 1x, /test.svg 2x')
})

it('should warn at most once even after state change', async () => {
const browser = await webdriver(appPort, '/warning-once')
await browser.eval(`document.querySelector("footer").scrollIntoView()`)
await browser.eval(`document.querySelector("button").click()`)
await browser.eval(`document.querySelector("button").click()`)
const count = await browser.eval(
`document.querySelector("button").textContent`
)
expect(count).toBe('Count: 2')
await check(async () => {
const result = await browser.eval(
'document.getElementById("w").naturalWidth'
)
if (result < 1) {
throw new Error('Image not loaded')
}
return 'done'
}, 'done')
const warnings = (await browser.log('browser'))
.map((log) => log.message)
.filter((log) => log.startsWith('Image with src'))
expect(warnings[0]).toMatch(
'Image with src "/test.png" has "sizes" property but it will be ignored.'
)
expect(warnings[1]).toMatch(
'Image with src "/test.png" was detected as the Largest Contentful Paint (LCP).'
)
expect(warnings.length).toBe(2)
})
} else {
//server-only tests
it('should not create an image folder in server/chunks', async () => {
Expand Down

0 comments on commit d87a7c8

Please sign in to comment.