diff --git a/packages/next/client/future/image.tsx b/packages/next/client/future/image.tsx
index 4ca2d06ec3c5..f3ffe5b7033e 100644
--- a/packages/next/client/future/image.tsx
+++ b/packages/next/client/future/image.tsx
@@ -591,8 +591,11 @@ export default function Image({
blurDataURL = blurDataURL || staticImageData.blurDataURL
staticSrc = staticImageData.src
- height = height || staticImageData.height
- width = width || staticImageData.width
+ // Ignore width and height (come from the bundler) when "fill" is used
+ if (!fill) {
+ height = height || staticImageData.height
+ width = width || staticImageData.width
+ }
if (!staticImageData.height || !staticImageData.width) {
throw new Error(
`An object should only be passed to the image component src parameter if it comes from a static image import. It must include height and width. Received ${JSON.stringify(
diff --git a/test/integration/image-future/default/pages/static-img.js b/test/integration/image-future/default/pages/static-img.js
index d5ce76c12898..6b6b4cfd5739 100644
--- a/test/integration/image-future/default/pages/static-img.js
+++ b/test/integration/image-future/default/pages/static-img.js
@@ -36,6 +36,10 @@ const Page = () => {
+
+
+
+
diff --git a/test/integration/image-future/default/test/static.test.ts b/test/integration/image-future/default/test/static.test.ts
index 7e02bf407b2b..e40d548ba17d 100644
--- a/test/integration/image-future/default/test/static.test.ts
+++ b/test/integration/image-future/default/test/static.test.ts
@@ -6,6 +6,7 @@ import {
renderViaHTTP,
File,
waitFor,
+ launchApp,
} from 'next-test-utils'
import webdriver from 'next-webdriver'
import { join } from 'path'
@@ -18,7 +19,7 @@ let html
const indexPage = new File(join(appDir, 'pages/static-img.js'))
-const runTests = () => {
+const runTests = (isDev = false) => {
it('Should allow an image with a static src to omit height and width', async () => {
expect(await browser.elementById('basic-static')).toBeTruthy()
expect(await browser.elementById('blur-png')).toBeTruthy()
@@ -29,44 +30,62 @@ const runTests = () => {
expect(await browser.elementById('static-gif')).toBeTruthy()
expect(await browser.elementById('static-bmp')).toBeTruthy()
expect(await browser.elementById('static-ico')).toBeTruthy()
+ expect(await browser.elementById('static-svg-fill')).toBeTruthy()
+ expect(await browser.elementById('static-gif-fill')).toBeTruthy()
+ expect(await browser.elementById('static-bmp-fill')).toBeTruthy()
+ expect(await browser.elementById('static-ico-fill')).toBeTruthy()
expect(await browser.elementById('static-unoptimized')).toBeTruthy()
})
- it('Should use immutable cache-control header for static import', async () => {
- await browser.eval(
- `document.getElementById("basic-static").scrollIntoView()`
- )
- await waitFor(1000)
- const url = await browser.eval(
- `document.getElementById("basic-static").src`
- )
- const res = await fetch(url)
- expect(res.headers.get('cache-control')).toBe(
- 'public, max-age=315360000, immutable'
- )
- })
- it('Should use immutable cache-control header even when unoptimized', async () => {
- await browser.eval(
- `document.getElementById("static-unoptimized").scrollIntoView()`
- )
- await waitFor(1000)
- const url = await browser.eval(
- `document.getElementById("static-unoptimized").src`
- )
- const res = await fetch(url)
- expect(res.headers.get('cache-control')).toBe(
- 'public, max-age=31536000, immutable'
- )
- })
+
+ if (!isDev) {
+ // cache-control is set to "0, no-store" in dev mode
+ it('Should use immutable cache-control header for static import', async () => {
+ await browser.eval(
+ `document.getElementById("basic-static").scrollIntoView()`
+ )
+ await waitFor(1000)
+ const url = await browser.eval(
+ `document.getElementById("basic-static").src`
+ )
+ const res = await fetch(url)
+ expect(res.headers.get('cache-control')).toBe(
+ 'public, max-age=315360000, immutable'
+ )
+ })
+
+ it('Should use immutable cache-control header even when unoptimized', async () => {
+ await browser.eval(
+ `document.getElementById("static-unoptimized").scrollIntoView()`
+ )
+ await waitFor(1000)
+ const url = await browser.eval(
+ `document.getElementById("static-unoptimized").src`
+ )
+ const res = await fetch(url)
+ expect(res.headers.get('cache-control')).toBe(
+ 'public, max-age=31536000, immutable'
+ )
+ })
+ }
it('Should automatically provide an image height and width', async () => {
expect(html).toContain('width="400" height="300"')
})
it('Should allow provided width and height to override intrinsic', async () => {
expect(html).toContain('width="150" height="150"')
})
+
it('Should add a blur to a statically imported image in "raw" mode', async () => {
- expect(html).toContain(
- `style="background-size:cover;background-position:0% 0%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Cfilter id='b' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='50'/%3E%3C/filter%3E%3Cimage filter='url(%23b)' x='0' y='0' height='100%25' width='100%25' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoKCgoKCgsMDAsPEA4QDxYUExMUFiIYGhgaGCIzICUgICUgMy03LCksNy1RQDg4QFFeT0pPXnFlZXGPiI+7u/sBCgoKCgoKCwwMCw8QDhAPFhQTExQWIhgaGBoYIjMgJSAgJSAzLTcsKSw3LVFAODhAUV5PSk9ecWVlcY+Ij7u7+//CABEIAAYACAMBIgACEQEDEQH/xAAnAAEBAAAAAAAAAAAAAAAAAAAABwEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAAmgP/xAAcEAACAQUBAAAAAAAAAAAAAAASFBMAAQMFERX/2gAIAQEAAT8AZ1HjrKZX55JysIc4Ff/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Af//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Af//Z'/%3E%3C/svg%3E")`
- )
+ // next-image-loader uses different blur behavior for dev/prod mode
+ // See next/build/webpack/loaders/next-image-loader
+ if (isDev) {
+ expect(html).toContain(
+ `style="background-size:cover;background-position:0% 0%;filter:blur(20px);background-image:url("/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftest-rect.f323a148.jpg&w=8&q=70")"`
+ )
+ } else {
+ expect(html).toContain(
+ `style="background-size:cover;background-position:0% 0%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Cfilter id='b' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='50'/%3E%3C/filter%3E%3Cimage filter='url(%23b)' x='0' y='0' height='100%25' width='100%25' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoKCgoKCgsMDAsPEA4QDxYUExMUFiIYGhgaGCIzICUgICUgMy03LCksNy1RQDg4QFFeT0pPXnFlZXGPiI+7u/sBCgoKCgoKCwwMCw8QDhAPFhQTExQWIhgaGBoYIjMgJSAgJSAzLTcsKSw3LVFAODhAUV5PSk9ecWVlcY+Ij7u7+//CABEIAAYACAMBIgACEQEDEQH/xAAnAAEBAAAAAAAAAAAAAAAAAAAABwEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAAmgP/xAAcEAACAQUBAAAAAAAAAAAAAAASFBMAAQMFERX/2gAIAQEAAT8AZ1HjrKZX55JysIc4Ff/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Af//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Af//Z'/%3E%3C/svg%3E")`
+ )
+ }
})
}
@@ -90,15 +109,30 @@ describe('Build Error Tests', () => {
})
})
describe('Future Static Image Component Tests', () => {
- beforeAll(async () => {
- await nextBuild(appDir)
- appPort = await findPort()
- app = await nextStart(appDir, appPort)
- html = await renderViaHTTP(appPort, '/static-img')
- browser = await webdriver(appPort, '/static-img')
+ describe('production mode', () => {
+ beforeAll(async () => {
+ await nextBuild(appDir)
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ html = await renderViaHTTP(appPort, '/static-img')
+ browser = await webdriver(appPort, '/static-img')
+ })
+ afterAll(() => {
+ killApp(app)
+ })
+ runTests(false)
})
- afterAll(() => {
- killApp(app)
+
+ describe('dev mode', () => {
+ beforeAll(async () => {
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ html = await renderViaHTTP(appPort, '/static-img')
+ browser = await webdriver(appPort, '/static-img')
+ })
+ afterAll(() => {
+ killApp(app)
+ })
+ runTests(true)
})
- runTests()
})