fix(image): match Next.js 16 default image sizes - #2704
Conversation
Next.js 16 removed the 16px default, but vinext continued generating and accepting it when imageSizes was unset. This added an unnecessary srcSet candidate and diverged from the pinned Next.js behavior. Use the shared server default for build-time defines and keep the client shim fallback aligned. Explicit imageSizes configurations that include 16px remain supported.
commit: |
Performance benchmarksCompared 0 improved · 0 regressed · 6 within ±1.5%
View detailed results and traces 🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head |
The Next.js 16 default-width change correctly updated generated App Router entries, but this behavior test still encoded the previous list. Align the expectation while preserving the neighboring explicit 16px opt-in coverage.
|
/bigbonk review for issues |
There was a problem hiding this comment.
Review: Next.js 16 default image sizes
The core change is correct and well-verified. I confirmed against next.js@v16.2.7/packages/next/src/shared/lib/image-config.ts that imageConfigDefault.imageSizes is exactly [32, 48, 64, 96, 128, 256, 384] — 16 was removed. All five source/test locations that carried the old default are updated consistently:
DEFAULT_IMAGE_SIZESinimage-optimization.ts(single source of truth)index.tsnow reusesDEFAULT_IMAGE_SIZESinstead of a hardcoded literal (good dedup)- shim fallback in
image.tsx(both theJSON.parsedefault string and thecatchfallback) - JSDoc in
next-config.ts - three test files
Behavior verification
I traced getImageWidths() in shims/image.tsx:324. For a 16px fixed image, targets are [16, 32]; the smallest configured width >= 16 is now 32 and >= 32 is 32, so both collapse to a single 32 candidate. The updated image-component.test.ts assertion (32 1x, no 16 candidate) correctly reflects this. The parseImageParams test changes (reject w=16, accept w=32/w=640 under defaults) also match the new allowlist.
The shims.test.ts case at line ~22596 still passes an explicit allowedWidths array containing 16, so w=16 is still accepted there — correctly preserving the "explicit config containing 16" path.
Non-blocking observations
No blocking issues. Two optional notes below. This change is a deliberate, documented Next.js 16 parity fix and looks ready to merge once CI is green.
| @@ -2267,7 +2267,7 @@ export default function vinext(options: VinextOptions = {}): PluginOption[] { | |||
| const deviceSizes = nextConfig.images?.deviceSizes ?? [ | |||
| 640, 750, 828, 1080, 1200, 1920, 2048, 3840, | |||
| ]; | |||
There was a problem hiding this comment.
Optional/pre-existing: since this block now reuses DEFAULT_IMAGE_SIZES for imageSizes (nice dedup), deviceSizes just above still uses a hardcoded literal while DEFAULT_DEVICE_SIZES is already imported (used at line 4902). Reusing it here too would keep both defaults in one place:
| ]; | |
| const deviceSizes = nextConfig.images?.deviceSizes ?? DEFAULT_DEVICE_SIZES; |
Not required for this PR — just flagging the asymmetry now that the sibling line was cleaned up.
|
Review posted successfully. SummaryI reviewed PR #2704 ( Findings:
One non-blocking suggestion posted inline: line 2267-2269 of No blocking issues. The change is a deliberate, well-documented Next.js 16 parity fix. |
Summary
images.imageSizesby removing16imageSizesconfigurations containing16supportedWhy
vinext is pinned to Next.js 16.2.7, but still used the pre-v16 default:
Next.js 16 removed
16because it is rarely requested and adds an unnecessarycandidate to responsive
srcsetoutput. The mismatch also meant vinext's imageoptimizer accepted a default width that Next.js 16 no longer accepts.
Behavior
w=16images.imageSizescontaining16Validation
vp test run tests/image-component.test.ts tests/shims.test.tsvp check packages/vinext/src/config/next-config.ts packages/vinext/src/index.ts packages/vinext/src/server/image-optimization.ts packages/vinext/src/shims/image.tsx tests/image-component.test.ts tests/shims.test.tsnode scripts/check-shim-types.mjsRisk
This is an intentional Next.js 16 compatibility change for projects that rely
on the default image sizes. Projects that still require 16px optimization can
opt back in with
images.imageSizes, matching Next.js's migration guidance.Explicit configurations are otherwise unchanged.
References