Skip to content

Commit

Permalink
Add next/image default loader errors (#18152)
Browse files Browse the repository at this point in the history
* Add next/image default loader errors

* Add domains check

* Apply suggestions from PR

* Update test
  • Loading branch information
ijjk committed Oct 25, 2020
1 parent 33eac8a commit 9c65c99
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 2 deletions.
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
44 changes: 43 additions & 1 deletion 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 All @@ -34,7 +35,12 @@ type ImageProps = Omit<
)

const imageData: ImageData = process.env.__NEXT_IMAGE_OPTS as any
const { sizes: configSizes, loader: configLoader, path: configPath } = imageData
const {
sizes: configSizes,
loader: configLoader,
path: configPath,
domains: configDomains,
} = imageData
configSizes.sort((a, b) => a - b) // smallest to largest
const largestSize = configSizes[configSizes.length - 1]

Expand Down Expand Up @@ -349,6 +355,42 @@ 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 Optimization requires ${missingValues.join(
', '
)} 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('/') && configDomains) {
let parsedSrc: URL
try {
parsedSrc = new URL(src)
} catch (err) {
console.error(err)
throw new Error(
`Failed to parse "${src}" if using relative image it must start with a leading slash "/" or be an absolute URL`
)
}

if (!configDomains.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
13 changes: 13 additions & 0 deletions test/integration/image-component/default/pages/invalid-src.js
@@ -0,0 +1,13 @@
import React from 'react'
import Image from 'next/image'

const Page = () => {
return (
<div>
<p>Hello World</p>
<Image src="https://google.com/test.png" unsized></Image>
</div>
)
}

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

const Page = () => {
return (
<div>
<Image width={200}></Image>
</div>
)
}

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 @@ -79,6 +81,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 Optimization 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

0 comments on commit 9c65c99

Please sign in to comment.