Image Optimizer
Roadmap — not yet available

Next.js image loader

An npm package, @image-optimizer/next, providing a next.config image loader that routes next/image through Image Optimizer instead of Next's built-in optimizer. This page documents the planned design; it is not implemented yet.

What Next.js already does for you

This is worth spelling out because it is the part that is easy to misjudge: when a next/image component renders with a sizes prop, Next computes the full list of widths to request from its images.deviceSizes / images.imageSizes config, and generates the srcset itself — including 1x/2x/3x device-pixel-ratio variants when no sizes prop is given. A custom loader does not need to reimplement any of that. Next calls the loader once per width it has already decided it needs:

type LoaderParams = { src: string; width: number; quality?: number }

function imageOptimizerLoader({ src, width, quality }: LoaderParams) {
  return `https://image-optimizer-two.vercel.app/img/${stripProtocol(src)}?w=${width}&q=${quality ?? 75}&f=auto`
}

That is the entire core of the loader — Next has already solved “what widths do I need.”

Wiring it up

next.config.ts
images: {
  loader: "custom",
  loaderFile: "./image-optimizer-loader.ts",
}

The part that is genuinely a gap: explicit per-breakpoint sizes

Next's automatic sizes-driven srcset assumes the image occupies a predictable fraction of the viewport. It does not have a concept of “60×60 on mobile, 300×200 on desktop” — art-directed, not just scaled, per breakpoint. The planned addition on top of the base loader is a small config that lets a project define what counts as each breakpoint and request explicit dimensions for it:

// image-optimizer.config.ts
export default {
  breakpoints: {
    mobile: { maxWidth: 640, width: 60, height: 60, fit: "crop" },
    desktop: { width: 300, height: 200, fit: "cover" },
  },
}

This is additive — the default loader behavior (driven entirely by Next's own sizes calculation) keeps working without any config at all.

Open questions

  • Whether breakpoint config should key off CSS media queries directly instead of a bespoke maxWidth field.
  • How this interacts with next/image's built-in blur placeholder, which expects the loader to also serve a tiny preview.