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 warning during next build when sharp is missing #27933

Merged
merged 9 commits into from Aug 11, 2021
16 changes: 16 additions & 0 deletions packages/next/build/index.ts
Expand Up @@ -930,6 +930,22 @@ export default async function build(
return returnValue
})

if (isNextImageImported) {
try {
if (process.env.NEXT_SHARP_PATH) {
require(process.env.NEXT_SHARP_PATH)
} else {
require.resolve('sharp', {
paths: [path.join(dir, 'node_modules')],
})
}
} catch (e) {
Log.warn(
'Detected `next/image` usage without `sharp`. https://nextjs.org/docs/messages/sharp-missing-in-production'
)
}
}

if (customAppGetInitialProps) {
console.warn(
chalk.bold.yellow(`Warning: `) +
Expand Down
51 changes: 39 additions & 12 deletions test/integration/image-optimizer/test/index.test.js
Expand Up @@ -23,10 +23,11 @@ const imagesDir = join(appDir, '.next', 'cache', 'images')
const nextConfig = new File(join(appDir, 'next.config.js'))
const largeSize = 1080 // defaults defined in server/config.ts
let nextOutput
let buildOutput
let appPort
let app

const sharpMissingText = `For production Image Optimization with Next.js, the optional 'sharp' package is strongly recommended`
const sharpRuntimeWarning = `For production Image Optimization with Next.js, the optional 'sharp' package is strongly recommended`
const sharpBuildWarning = 'Detected `next/image` usage without `sharp`.'

async function fsToJson(dir, output = {}) {
const files = await fs.readdir(dir)
Expand Down Expand Up @@ -726,13 +727,29 @@ function runTests({ w, isDev, domains = [], ttl, isSharp }) {
expect(Object.keys(json1).length).toBe(1)
})

if (isDev || isSharp) {
it('should not have sharp missing warning', () => {
expect(nextOutput).not.toContain(sharpMissingText)
if (isDev) {
it('should not have runtime warning in dev', () => {
expect(nextOutput).not.toContain(sharpRuntimeWarning)
})

it('should not have build warning in dev', () => {
expect(buildOutput).not.toContain(sharpBuildWarning)
})
} else if (isSharp) {
it('should not have runtime warning when sharp is installed', () => {
expect(nextOutput).not.toContain(sharpRuntimeWarning)
})

it('should not have build warning when sharp is installed', () => {
expect(buildOutput).not.toContain(sharpBuildWarning)
})
} else {
it('should have sharp missing warning', () => {
expect(nextOutput).toContain(sharpMissingText)
it('should have runtime warning when sharp is not installed', () => {
expect(nextOutput).toContain(sharpRuntimeWarning)
})

it('should have build warning when sharp is not installed', () => {
expect(buildOutput).toContain(sharpBuildWarning)
})
}
}
Expand Down Expand Up @@ -910,8 +927,10 @@ describe('Image Optimizer', () => {
},
})
nextOutput = ''
buildOutput = ''
nextConfig.replace('{ /* replaceme */ }', json)
await nextBuild(appDir)
const out = await nextBuild(appDir, [], { stderr: true })
buildOutput = out.stderr
appPort = await findPort()
app = await nextStart(appDir, appPort, {
onStderr(msg) {
Expand Down Expand Up @@ -949,7 +968,8 @@ describe('Image Optimizer', () => {
},
}`
)
await nextBuild(appDir)
const out = await nextBuild(appDir, [], { stderr: true })
buildOutput = out.stderr
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
Expand Down Expand Up @@ -1025,7 +1045,8 @@ describe('Image Optimizer', () => {
},
}`
nextConfig.replace('{ /* replaceme */ }', newConfig)
await nextBuild(appDir)
const out = await nextBuild(appDir, [], { stderr: true })
buildOutput = out.stderr
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
Expand Down Expand Up @@ -1084,6 +1105,7 @@ describe('Image Optimizer', () => {
const size = 384 // defaults defined in server/config.ts
beforeAll(async () => {
nextOutput = ''
buildOutput = ''
appPort = await findPort()
app = await launchApp(appDir, appPort, {
onStderr(msg) {
Expand Down Expand Up @@ -1111,6 +1133,7 @@ describe('Image Optimizer', () => {
},
})
nextOutput = ''
buildOutput = ''
nextConfig.replace('{ /* replaceme */ }', json)
appPort = await findPort()
app = await launchApp(appDir, appPort, {
Expand All @@ -1133,7 +1156,9 @@ describe('Image Optimizer', () => {
const size = 384 // defaults defined in server/config.ts
beforeAll(async () => {
nextOutput = ''
await nextBuild(appDir)
buildOutput = ''
const out = await nextBuild(appDir, [], { stderr: true })
buildOutput = out.stderr
appPort = await findPort()
app = await nextStart(appDir, appPort, {
onStderr(msg) {
Expand Down Expand Up @@ -1167,8 +1192,10 @@ describe('Image Optimizer', () => {
},
})
nextOutput = ''
buildOutput = ''
nextConfig.replace('{ /* replaceme */ }', json)
await nextBuild(appDir)
const out = await nextBuild(appDir, [], { stderr: true })
buildOutput = out.stderr
appPort = await findPort()
app = await nextStart(appDir, appPort, {
onStderr(msg) {
Expand Down