Skip to content

Commit

Permalink
fix(next/image): improve svg heuristic for unoptimized (vercel#72970)
Browse files Browse the repository at this point in the history
The `<Image>` component doesn't optimize SVG images since they are
vector images and can already scale up and down to any width.

Therefore, the component will try to detect SVG images based on the file
name to avoid sending them to the Image Optimization API at all. This is
because the default behavior of the Image Optimization API is to error
for SVG images due to the security implications of `<svg>` with nested
`<script>`, etc (unless `dangerouslyAllowSVG` is enabled.

However, we don't want users to reach for `dangerouslyAllowSVG` because
it is not usually what they intended. So instead, we can improve the
heuristic for detecting SVG in the `<Image>` component by ignoring the
query string.

Related to nodejs/nodejs.org#7244
  • Loading branch information
styfle authored Nov 20, 2024
1 parent 9db3c0e commit 7e22452
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/next/src/client/legacy/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ function defaultLoader({
}
}

if (src.endsWith('.svg') && !config.dangerouslyAllowSVG) {
if (!config.dangerouslyAllowSVG && src.split('?', 1)[0].endsWith('.svg')) {
// Special case to make svg serve as-is to avoid proxying
// through the built-in Image Optimization API.
return src
Expand Down
6 changes: 5 additions & 1 deletion packages/next/src/shared/lib/get-img-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,11 @@ export function getImgProps(
if (config.unoptimized) {
unoptimized = true
}
if (isDefaultLoader && src.endsWith('.svg') && !config.dangerouslyAllowSVG) {
if (
isDefaultLoader &&
!config.dangerouslyAllowSVG &&
src.split('?', 1)[0].endsWith('.svg')
) {
// Special case to make svg serve as-is to avoid proxying
// through the built-in Image Optimization API.
unoptimized = true
Expand Down
72 changes: 72 additions & 0 deletions test/unit/next-image-get-img-props.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,76 @@ describe('getImageProps()', () => {
['src', '/_next/image?url=%2Ftest.png&w=256&q=75'],
])
})
it('should auto unoptimized for relative svg', async () => {
const { props } = getImageProps({
alt: 'a nice desc',
src: '/test.svg',
width: 100,
height: 200,
})
expect(warningMessages).toStrictEqual([])
expect(Object.entries(props)).toStrictEqual([
['alt', 'a nice desc'],
['loading', 'lazy'],
['width', 100],
['height', 200],
['decoding', 'async'],
['style', { color: 'transparent' }],
['src', '/test.svg'],
])
})
it('should auto unoptimized for relative svg with query', async () => {
const { props } = getImageProps({
alt: 'a nice desc',
src: '/test.svg?v=1',
width: 100,
height: 200,
})
expect(warningMessages).toStrictEqual([])
expect(Object.entries(props)).toStrictEqual([
['alt', 'a nice desc'],
['loading', 'lazy'],
['width', 100],
['height', 200],
['decoding', 'async'],
['style', { color: 'transparent' }],
['src', '/test.svg?v=1'],
])
})
it('should auto unoptimized for absolute svg', async () => {
const { props } = getImageProps({
alt: 'a nice desc',
src: 'https://example.com/test.svg',
width: 100,
height: 200,
})
expect(warningMessages).toStrictEqual([])
expect(Object.entries(props)).toStrictEqual([
['alt', 'a nice desc'],
['loading', 'lazy'],
['width', 100],
['height', 200],
['decoding', 'async'],
['style', { color: 'transparent' }],
['src', 'https://example.com/test.svg'],
])
})
it('should auto unoptimized for absolute svg with query', async () => {
const { props } = getImageProps({
alt: 'a nice desc',
src: 'https://example.com/test.svg?v=1',
width: 100,
height: 200,
})
expect(warningMessages).toStrictEqual([])
expect(Object.entries(props)).toStrictEqual([
['alt', 'a nice desc'],
['loading', 'lazy'],
['width', 100],
['height', 200],
['decoding', 'async'],
['style', { color: 'transparent' }],
['src', 'https://example.com/test.svg?v=1'],
])
})
})

0 comments on commit 7e22452

Please sign in to comment.