next/image srcset Generator
Hard · Images
The <Image> component from next/image does not render your src directly. It builds a srcset of URLs pointing at the built-in optimizer (/_next/image?url=...&w=...&q=...), so the browser can download the smallest file that looks sharp. Write getImageProps(props, config) that reproduces this logic (the getWidths function in Next.js get-img-props.ts) with the Next.js 16 defaults.
props has src, and optionally width, fill, sizes, quality, unoptimized. config may override deviceSizes, imageSizes, qualities and unoptimized. Defaults: deviceSizes [640, 750, 828, 1080, 1200, 1920, 2048, 3840], imageSizes [32, 48, 64, 96, 128, 256, 384] (Next 16 removed 16), qualities [75] (Next 16 changed it from 1..100).
- The image is unoptimized if props.unoptimized or config.unoptimized is true, if src starts with data: or blob:, or if the path part of src (before ?) ends with .svg (SVG is served as-is unless dangerouslyAllowSVG is set). Then return { src, srcSet: undefined, sizes: undefined }.
- allSizes = device sizes and image sizes together, sorted ascending.
- If sizes is set: collect every number before vw that matches the regex /(^|\s)(1?\d?\d)vw/g. If there are any, the widths are the allSizes that are >= deviceSizes[0] * smallest / 100; if there are none, use all of allSizes. Descriptors are w.
- Else if there is no width (for example fill): widths = deviceSizes, descriptors w.
- Else: for width and width * 2, take the first entry of allSizes that is >= w (or the largest one), remove duplicates, and use 1x, 2x descriptors.
- Quality: q = quality || 75, then pick the value in qualities (sorted ascending) closest to q; on a tie keep the smaller one.
- Each URL is "/_next/image?url=" + encodeURIComponent(src) + "&w=" + width + "&q=" + q. srcSet joins "<url> <width>w" (or "<url> <n>x") with ", ". src is the URL of the last (largest) width.
- sizes is "100vw" when no sizes was given and descriptors are w; otherwise it is the given sizes (possibly undefined).