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

Add next/image default loader errors #18152

Merged
merged 10 commits into from Oct 25, 2020
6 changes: 6 additions & 0 deletions packages/next/build/webpack-config.ts
Expand Up @@ -994,6 +994,12 @@ export default async function getBaseWebpackConfig(
sizes: config.images.sizes,
path: config.images.path,
loader: config.images.loader,
...(dev
? {
// pass domains in development to allow validating on the client
domains: config.images.domains,
}
: {}),
}),
'process.env.__NEXT_ROUTER_BASEPATH': JSON.stringify(config.basePath),
'process.env.__NEXT_HAS_REWRITES': JSON.stringify(hasRewrites),
Expand Down
29 changes: 29 additions & 0 deletions packages/next/client/image.tsx
Expand Up @@ -17,6 +17,7 @@ type ImageData = {
sizes: number[]
loader: LoaderKey
path: string
domains?: string[]
}

type ImageProps = Omit<
Expand Down Expand Up @@ -341,6 +342,34 @@ function cloudinaryLoader({ root, src, width, quality }: LoaderProps): string {
}

function defaultLoader({ root, src, width, quality }: LoaderProps): string {
if (process.env.NODE_ENV !== 'production') {
const missingValues = []

// these should always be provided but make sure they are
if (!src) missingValues.push('src')
if (!width) missingValues.push('width')

if (missingValues.length > 0) {
throw new Error(
`Next Image optimizer requires ${missingValues.join(
ijjk marked this conversation as resolved.
Show resolved Hide resolved
', '
)} to be provided. Make sure you pass them as props to the \`next/image\` component. Received: ${JSON.stringify(
{ src, width, quality }
)}`
)
}

if (src && !src.startsWith('/') && imageData.domains) {
ijjk marked this conversation as resolved.
Show resolved Hide resolved
const parsedSrc = new URL(src)
ijjk marked this conversation as resolved.
Show resolved Hide resolved

if (!imageData.domains.includes(parsedSrc.hostname)) {
throw new Error(
`Invalid src prop (${src}) on \`next/image\`, hostname is not configured under images in your \`next.config.js\``
)
}
}
}

return `${root}?url=${encodeURIComponent(src)}&w=${width}&q=${
quality || '100'
}`
Expand Down
18 changes: 18 additions & 0 deletions test/integration/image-component/default/pages/invalid-src.js
@@ -0,0 +1,18 @@
import React from 'react'
import Image from 'next/image'

const Page = () => {
return (
<div>
<p>Hello World</p>
<Image
id="unsized-image"
src="https://google.com/test.png"
unsized
></Image>
<p id="stubtext">This is the index page</p>
ijjk marked this conversation as resolved.
Show resolved Hide resolved
</div>
)
}

export default Page
14 changes: 14 additions & 0 deletions test/integration/image-component/default/pages/missing-src.js
@@ -0,0 +1,14 @@
import React from 'react'
import Image from 'next/image'

const Page = () => {
return (
<div>
<p>Hello World</p>
<Image id="unsized-image" width={200}></Image>
ijjk marked this conversation as resolved.
Show resolved Hide resolved
<p id="stubtext">This is the index page</p>
</div>
)
}

ijjk marked this conversation as resolved.
Show resolved Hide resolved
export default Page
24 changes: 23 additions & 1 deletion test/integration/image-component/default/test/index.test.js
Expand Up @@ -8,6 +8,8 @@ import {
nextStart,
nextBuild,
check,
hasRedbox,
getRedboxHeader,
} from 'next-test-utils'
import webdriver from 'next-webdriver'
import fs from 'fs-extra'
Expand All @@ -20,7 +22,7 @@ const nextConfig = join(appDir, 'next.config.js')
let appPort
let app

function runTests() {
function runTests(mode) {
it('should load the images', async () => {
let browser
try {
Expand Down Expand Up @@ -73,6 +75,26 @@ function runTests() {
}
}
})

if (mode === 'dev') {
it('should show missing src error', async () => {
const browser = await webdriver(appPort, '/missing-src')

await hasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain(
'Next Image optimizer requires src to be provided. Make sure you pass them as props to the `next/image` component. Received: {"width":1200}'
)
})

it('should show invalid src error', async () => {
const browser = await webdriver(appPort, '/invalid-src')

await hasRedbox(browser)
expect(await getRedboxHeader(browser)).toContain(
'Invalid src prop (https://google.com/test.png) on `next/image`, hostname is not configured under images in your `next.config.js`'
)
})
}
}

describe('Image Component Tests', () => {
Expand Down