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

Rename iconSizes to imageSizes, remove size limitation #18294

Merged
merged 2 commits into from Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/basic-features/image-optimization.md
Expand Up @@ -62,14 +62,14 @@ module.exports = {
}
```

### Icon Sizes
### Image Sizes

You can specify a list of icon image widths using the `iconSizes` property. These widths should be smaller than the smallest value in `deviceSizes`. The purpose is for images that don't scale with the browser window, such as icons or badges. If `iconSizes` is not defined, then `deviceSizes` will be used.
You can specify a list of exact image widths using the `imageSizes` property. These widths should be different than the widths defined in `deviceSizes`. The purpose is for images that don't scale with the browser window, such as icons, badges, or profile images. If the `width` property of a [`next/image`](/docs/api-reference/next/image.md) component matches a value in `imageSizes`, the image will be rendered at that exact width.

```js
module.exports = {
images: {
iconSizes: [16, 32, 64],
imageSizes: [16, 32, 64],
},
}
```
Expand Down
4 changes: 2 additions & 2 deletions packages/next/build/index.ts
Expand Up @@ -1111,8 +1111,8 @@ export default async function build(
}

const images = { ...config.images }
const { deviceSizes, iconSizes } = images
images.sizes = [...deviceSizes, ...iconSizes]
const { deviceSizes, imageSizes } = images
images.sizes = [...deviceSizes, ...imageSizes]

await promises.writeFile(
path.join(distDir, IMAGES_MANIFEST),
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/webpack-config.ts
Expand Up @@ -992,7 +992,7 @@ export default async function getBaseWebpackConfig(
),
'process.env.__NEXT_IMAGE_OPTS': JSON.stringify({
deviceSizes: config.images.deviceSizes,
iconSizes: config.images.iconSizes,
imageSizes: config.images.imageSizes,
path: config.images.path,
loader: config.images.loader,
...(dev
Expand Down
9 changes: 4 additions & 5 deletions packages/next/client/image.tsx
Expand Up @@ -15,7 +15,7 @@ type LoaderKey = 'imgix' | 'cloudinary' | 'akamai' | 'default'

type ImageData = {
deviceSizes: number[]
iconSizes: number[]
imageSizes: number[]
loader: LoaderKey
path: string
domains?: string[]
Expand All @@ -38,14 +38,14 @@ type ImageProps = Omit<
const imageData: ImageData = process.env.__NEXT_IMAGE_OPTS as any
const {
deviceSizes: configDeviceSizes,
iconSizes: configIconSizes,
imageSizes: configImageSizes,
loader: configLoader,
path: configPath,
domains: configDomains,
} = imageData
// sort smallest to largest
configDeviceSizes.sort((a, b) => a - b)
configIconSizes.sort((a, b) => a - b)
configImageSizes.sort((a, b) => a - b)

let cachedObserver: IntersectionObserver
const IntersectionObserver =
Expand Down Expand Up @@ -87,8 +87,7 @@ function getDeviceSizes(width: number | undefined): number[] {
if (typeof width !== 'number') {
return configDeviceSizes
}
const smallest = configDeviceSizes[0]
if (width < smallest && configIconSizes.includes(width)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to this logic?

Copy link
Member Author

@styfle styfle Oct 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We found a use case where we would want to opt-out of the srcset behavior, even with a slightly larger image (for example 400px even though the smallest device is 320px)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better solution might be a another property on the component but then you have two things you need to configure because we still need to know the device sizes

if (configImageSizes.includes(width)) {
return [width]
}
const widths: number[] = []
Expand Down
18 changes: 9 additions & 9 deletions packages/next/next-server/server/config.ts
Expand Up @@ -26,7 +26,7 @@ const defaultConfig: { [key: string]: any } = {
analyticsId: process.env.VERCEL_ANALYTICS_ID || '',
images: {
deviceSizes: [320, 420, 768, 1024, 1200],
iconSizes: [],
imageSizes: [],
domains: [],
path: '/_next/image',
loader: 'default',
Expand Down Expand Up @@ -280,27 +280,27 @@ function assignDefaults(userConfig: { [key: string]: any }) {
)
}
}
if (images.iconSizes) {
const { iconSizes } = images
if (!Array.isArray(iconSizes)) {
if (images.imageSizes) {
const { imageSizes } = images
if (!Array.isArray(imageSizes)) {
throw new Error(
`Specified images.iconSizes should be an Array received ${typeof iconSizes}`
`Specified images.imageSizes should be an Array received ${typeof imageSizes}`
)
}

if (iconSizes.length > 25) {
if (imageSizes.length > 25) {
throw new Error(
`Specified images.iconSizes exceeds length of 25, received length (${iconSizes.length}), please reduce the length of the array to continue`
`Specified images.imageSizes exceeds length of 25, received length (${imageSizes.length}), please reduce the length of the array to continue`
)
}

const invalid = iconSizes.filter((d: unknown) => {
const invalid = imageSizes.filter((d: unknown) => {
return typeof d !== 'number' || d < 1 || d > 10000
})

if (invalid.length > 0) {
throw new Error(
`Specified images.iconSizes should be an Array of numbers that are between 1 and 10000, received invalid values (${invalid.join(
`Specified images.imageSizes should be an Array of numbers that are between 1 and 10000, received invalid values (${invalid.join(
', '
)})`
)
Expand Down
6 changes: 3 additions & 3 deletions packages/next/next-server/server/image-optimizer.ts
Expand Up @@ -25,7 +25,7 @@ const VECTOR_TYPES = [SVG]

type ImageData = {
deviceSizes: number[]
iconSizes: number[]
imageSizes: number[]
loader: string
path: string
domains?: string[]
Expand All @@ -39,8 +39,8 @@ export async function imageOptimizer(
) {
const { nextConfig, distDir } = server
const imageData: ImageData = nextConfig.images
const { deviceSizes = [], iconSizes = [], domains = [], loader } = imageData
const sizes = [...deviceSizes, ...iconSizes]
const { deviceSizes = [], imageSizes = [], domains = [], loader } = imageData
const sizes = [...deviceSizes, ...imageSizes]

if (loader !== 'default') {
await server.render404(req, res, parsedUrl)
Expand Down
2 changes: 1 addition & 1 deletion test/integration/image-component/basic/next.config.js
@@ -1,7 +1,7 @@
module.exports = {
images: {
deviceSizes: [480, 1024, 1600, 2000],
iconSizes: [16, 64],
imageSizes: [16, 64],
path: 'https://example.com/myaccount/',
loader: 'imgix',
},
Expand Down
Expand Up @@ -51,7 +51,7 @@ function runTests() {
await browser.elementById('preceding-slash-image').getAttribute('srcset')
).toBe('https://example.com/myaccount/fooslash.jpg?auto=format&w=480 480w')
})
it('should use iconSizes when width matches, not deviceSizes from next.config.js', async () => {
it('should use imageSizes when width matches, not deviceSizes from next.config.js', async () => {
expect(await browser.elementById('icon-image-16').getAttribute('src')).toBe(
'https://example.com/myaccount/icon.png?auto=format&w=16'
)
Expand Down
8 changes: 4 additions & 4 deletions test/integration/image-optimizer/test/index.test.js
Expand Up @@ -398,12 +398,12 @@ describe('Image Optimizer', () => {
)
})

it('should error when iconSizes contains invalid widths', async () => {
it('should error when imageSizes contains invalid widths', async () => {
await nextConfig.replace(
'{ /* replaceme */ }',
JSON.stringify({
images: {
iconSizes: [0, 16, 64, 12000],
imageSizes: [0, 16, 64, 12000],
},
})
)
Expand All @@ -419,7 +419,7 @@ describe('Image Optimizer', () => {
await nextConfig.restore()

expect(stderr).toContain(
'Specified images.iconSizes should be an Array of numbers that are between 1 and 10000, received invalid values (0, 12000)'
'Specified images.imageSizes should be an Array of numbers that are between 1 and 10000, received invalid values (0, 12000)'
)
})
})
Expand Down Expand Up @@ -447,7 +447,7 @@ describe('Image Optimizer', () => {
const json = JSON.stringify({
images: {
deviceSizes: [largeSize],
iconSizes: [size],
imageSizes: [size],
domains,
},
})
Expand Down