Skip to content

Commit 2264d35

Browse files
authored
Fix .svg image optimization with a loader prop (#34452)
* Fix .svg image optimization with a `loader` prop * Add test * Revert test back to 266x266
1 parent 59714db commit 2264d35

File tree

3 files changed

+54
-6
lines changed

3 files changed

+54
-6
lines changed

packages/next/client/image.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,6 @@ export default function Image({
385385
isLazy = false
386386
}
387387

388-
if (src.endsWith('.svg') && !config.dangerouslyAllowSVG) {
389-
unoptimized = true
390-
}
391-
392388
if (process.env.NODE_ENV !== 'production') {
393389
if (!src) {
394390
throw new Error(
@@ -466,7 +462,7 @@ export default function Image({
466462
)
467463
}
468464

469-
if (!unoptimized) {
465+
if (!unoptimized && loader !== defaultImageLoader) {
470466
const urlStr = loader({
471467
config,
472468
src,
@@ -866,6 +862,12 @@ function defaultLoader({
866862
}
867863
}
868864

865+
if (src.endsWith('.svg') && !config.dangerouslyAllowSVG) {
866+
// Special case to make svg serve as-is to avoid proxying
867+
// through the built-in Image Optimization API.
868+
return src
869+
}
870+
869871
return `${config.path}?url=${encodeURIComponent(src)}&w=${width}&q=${
870872
quality || 75
871873
}`
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react'
2+
import Image from 'next/image'
3+
4+
const Page = () => {
5+
return (
6+
<div>
7+
<h1>Should work with SVG</h1>
8+
<Image
9+
id="with-loader"
10+
src="/test.svg"
11+
width={100}
12+
height={100}
13+
loader={({ src, width }) => `${src}?size=${width}`}
14+
/>
15+
<br />
16+
<Image id="without-loader" src="/test.svg" width={100} height={100} />
17+
<footer>footer</footer>
18+
</div>
19+
)
20+
}
21+
22+
export default Page

test/integration/image-component/default/test/index.test.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ function runTests(mode) {
224224
)
225225
await check(
226226
() => browser.eval(`document.getElementById("msg3").textContent`),
227-
'loaded 1 img3 with dimensions 400x400'
227+
'loaded 1 img3 with dimensions 266x266'
228228
)
229229
await check(
230230
() => browser.eval(`document.getElementById("msg4").textContent`),
@@ -785,6 +785,30 @@ function runTests(mode) {
785785
/Image with src (.*)gif(.*) has "sizes" property but it will be ignored/gm
786786
)
787787
})
788+
789+
it('should not warn when svg, even if with loader prop or without', async () => {
790+
const browser = await webdriver(appPort, '/loader-svg')
791+
await browser.eval(`document.querySelector("footer").scrollIntoView()`)
792+
const warnings = (await browser.log('browser'))
793+
.map((log) => log.message)
794+
.join('\n')
795+
expect(await hasRedbox(browser)).toBe(false)
796+
expect(warnings).not.toMatch(
797+
/Image with src (.*) has a "loader" property that does not implement width/gm
798+
)
799+
expect(await browser.elementById('with-loader').getAttribute('src')).toBe(
800+
'/test.svg?size=256'
801+
)
802+
expect(
803+
await browser.elementById('with-loader').getAttribute('srcset')
804+
).toBe('/test.svg?size=128 1x, /test.svg?size=256 2x')
805+
expect(
806+
await browser.elementById('without-loader').getAttribute('src')
807+
).toBe('/test.svg')
808+
expect(
809+
await browser.elementById('without-loader').getAttribute('srcset')
810+
).toBe('/test.svg 1x, /test.svg 2x')
811+
})
788812
} else {
789813
//server-only tests
790814
it('should not create an image folder in server/chunks', async () => {

0 commit comments

Comments
 (0)