Blog/Developer Tools
Developer ToolsOctober 2026 · 11 min read

Next.js Image Optimization: Why You Should Still Compress Images Before Deploy

next/image resizes and converts images on demand, but it starts from your source files. Compressing and right-sizing those sources before you commit them reduces repository size, upload and build time, optimizer workload and the quality ceiling of every variant Next.js generates.

The Next.js Image component is one of the framework's best features. You pass it a source file, it serves a resized, modern-format version to each visitor, lazy-loads it and reserves layout space to prevent shifts. Many teams conclude from this that image optimization is solved and drop 6000 pixel PNG exports straight into the public folder. That works, in the sense that pages still render. But it leaves real performance and cost on the table, and it quietly makes every deploy heavier. This guide explains what next/image does and does not do, why the source file still matters, and a practical workflow that combines pre-compression with the component for the best results.

Check your version

Defaults for the Image component, such as supported formats, quality values and caching behavior, have changed between Next.js releases. The statements below describe common behavior. Confirm details in the documentation for the version you run.

What next/image actually does

The Image component, together with the built-in optimizer, performs several jobs at request time.

  • Resizing. It generates a version of the image at a width appropriate for the device, using the widths configured for the project and the sizes attribute you provide.
  • Format conversion. By default it can serve WebP to browsers that support it, and AVIF can be enabled through configuration so that it is served first where supported.
  • Lazy loading. Images outside the viewport load only when needed unless you mark them as priority.
  • Layout stability. Width and height, or a fill layout, reserve space so the page does not jump as images arrive.
  • Caching. Optimized variants are cached so later requests are served quickly.

What it does not do is fix a bad source. It cannot recover quality that is missing, and it cannot make an enormous original cheap to process, store or fetch.

Why the source file still matters

1. Repository and deploy size

Every image in your project lives in version control and ships in each deployment package or is uploaded to your platform. A folder of unoptimized exports can add hundreds of megabytes to a repository. Clones become slow, continuous integration spends longer checking out code and every preview deployment moves the same heavy files again.

2. Optimizer workload and first-request latency

On-demand optimization means the first visitor to request a given variant waits while the server decodes the original, resizes it and encodes the result. A 25 megabyte PNG takes much longer to decode than a 400 kilobyte one. Starting from a sensibly sized, compressed source makes the cold path faster and reduces memory use on the server or serverless function that does the work.

3. Platform usage and cost

Some hosting platforms meter image optimization, for example by the number of source images optimized or by transformations and bandwidth, depending on plan. Smaller sources reduce bandwidth between your storage and the optimizer. Review your hosting provider's current pricing and limits rather than assuming, because they change.

4. Build time for static imports

When you import an image statically, Next.js reads it at build time to determine its dimensions and generate a blur placeholder. Large files slow that step, and a project with hundreds of them can notice the difference in build duration.

5. Quality compounds

Lossy encoding applies on top of whatever the source contains. If your source is a heavily compressed JPEG with blocky artifacts, the optimizer's WebP or AVIF output inherits and sometimes amplifies those artifacts. Start from a clean, high-quality source, and generate variants once, rather than recompressing already degraded images.

Right-size the source first

The simplest and largest win is to avoid shipping pixels that no visitor can use. Work out the widest rendered width of the image, then multiply by the maximum device pixel ratio you want to support, usually two. A hero displayed up to 1440 CSS pixels wide needs at most 2880 pixels of source. A card image displayed at 400 CSS pixels wide needs at most 800.

Use caseMax rendered widthSource width to keep
Full-width hero1440 px2880 px or less
Article body image720 px1440 px
Card thumbnail400 px800 px
Avatar96 px192 px
Logo200 px400 px, or use SVG

These are guidelines. If your design allows zooming on product images, keep more resolution for those. The point is to decide deliberately instead of keeping whatever the designer exported.

Choose the right format for the source

The source format influences everything downstream. For photographs, a high-quality JPEG is a good source because it is small and universally decodable. For screenshots, illustrations and graphics with transparency, a PNG is the right source, optimized losslessly or quantized if the artwork allows. For vector logos and icons, use SVG and render it with a plain image tag or inline, since raster optimization is not needed.

Avoid keeping oversized lossless masters in the public directory. Store them in a design archive or a separate assets repository, and keep only the delivery-ready source in the project.

Compress the source before you commit

Once the size is right, compress. For PNG sources, lossless optimization is a risk-free first pass. Lossy quantization is worth testing on flat illustrations and interface screenshots. For JPEG sources, re-encoding with an optimized encoder such as MozJPEG often reduces the file without visible change. Compare outputs at full size and keep the original masters elsewhere.

TinyPixels is built for this step. It runs locally on macOS and Windows, compresses PNG and JPEG with oxipng, imagequant and MozJPEG, handles whole folders in parallel and has a watch-folder mode that compresses new files as they appear in your project directory. No uploads, no npm dependency and no build plugin, and Pro is a one-time purchase. Our guide on optimizing Next.js images describes a setup in more detail.

Configure next/image for modern formats

In your Next.js configuration you can specify the formats the optimizer may generate. Listing AVIF before WebP lets supporting browsers receive the smallest option, at the cost of slower encoding on the first request.

// next.config.ts
const nextConfig = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
};
export default nextConfig;

AVIF generally compresses better than WebP but takes longer to encode. If you see slow first requests or high CPU on the optimizer, try WebP only, or rely on pre-generated variants for your most important images. Test both with your own content.

Use sizes correctly

The sizes attribute tells the browser how wide the image will be at different viewport widths so it can choose the right candidate from the generated set. Without it, the component assumes the image may be as wide as the viewport and can request a larger file than necessary. A card grid that shows three columns on desktop should say so.

<Image
  src="/cards/hero.jpg"
  alt="Product overview"
  width={1200}
  height={800}
  sizes="(min-width: 1024px) 33vw, 100vw"
/>

Always supply meaningful alt text. It helps accessibility and gives search engines context.

Priority and LCP

The largest visible image above the fold is often the Largest Contentful Paint element. Lazy-loading it delays LCP. Mark the hero image as priority, so it is preloaded, and keep it small. Do not mark many images as priority, or you dilute the benefit. For below-the-fold images, keep the default lazy loading.

A pre-compressed hero reduces the bytes the browser must fetch even after the optimizer has resized it, and it shortens the cold-start path on the first request. Combined with correct sizes and priority, it is the most reliable way to improve LCP for image-led pages.

Quality values

The Image component accepts a quality setting, and recent versions have introduced configuration that controls which values are allowed. A value around 75 is a common default and works for most photographs. Going much lower makes artifacts visible, and going much higher increases bytes for little visible gain. Treat it as a global default and adjust only for images where you see a problem.

What about remote images and a CMS?

If images come from a headless CMS or object storage, next/image can optimize them through configured remote patterns. The same principle applies: compress and right-size at upload time. Set a maximum upload dimension in your CMS, run a compression step in the upload pipeline or ask editors to export from a tool that compresses locally, so heavy originals never become your delivery source.

A workflow that scales

  1. Designers export at the largest size needed, no more, into a shared folder.
  2. A local watch folder compresses new files automatically.
  3. Developers copy delivery-ready files into the project and use next/image with width, height and sizes set.
  4. The hero is marked priority. Everything else is lazy.
  5. Formats are configured for AVIF and WebP, and the team measures first-request latency.
  6. Lighthouse and field data from real users confirm the improvements.

Common mistakes

  • Committing full-resolution camera or design exports.
  • Forgetting sizes and serving images that are too wide.
  • Marking every image as priority.
  • Using unoptimized for convenience and shipping the raw file to browsers.
  • Compressing already compressed JPEGs repeatedly.
  • Ignoring alt text and layout dimensions.

Static export and self-hosted deployments

Not every Next.js project uses the built-in optimizer. If you deploy as a static export, the on-demand image server is not available, and you either configure a custom image loader that points at an external service or serve the files unoptimized. In that situation pre-compression stops being a nice improvement and becomes the entire optimization strategy. Every visitor downloads exactly the file you commit, so right-sizing and compressing it is the main lever you have over page weight.

Self-hosted deployments behave differently again. The optimizer runs on your own server, so image work competes with rendering for CPU and memory. Compressed sources reduce that load, and a longer cache lifetime for optimized variants reduces repeat work. If you run on small instances, watch memory when many large images are requested at once, because decoding enormous originals is where processes tend to run out of memory.

Measuring the improvement

Do not trust intuition about image work. Measure before and after with the same tools every time. Use Lighthouse for a controlled lab run and compare Largest Contentful Paint and total transferred bytes. Use real-user monitoring or your hosting analytics to see field data, since lab numbers on a fast laptop hide the experience on a mid-range phone. Record repository size, build duration and first-request latency for a few representative pages. A short table in your pull request showing before and after numbers makes the value of the work obvious to reviewers and prevents regressions later.

Also test with throttled networking. Pages that feel fine on office Wi-Fi can be painfully slow on a congested mobile connection, and image bytes are the most common reason. Seeing a hero image arrive in a fraction of the time after pre-compression is usually the argument that convinces a team to adopt the workflow permanently.

Conclusion

next/image is an excellent delivery layer, not a substitute for good sources. Right-size and compress images before they enter the repository, then let the component handle responsive variants, modern formats and lazy loading. The result is a lighter repository, faster builds, cheaper optimizer work and better Core Web Vitals, with no change to how your pages look.

Frequently asked questions

Do I still need to compress images if I use next/image?

Yes, it helps. The optimizer starts from your source file, so smaller and correctly sized sources reduce repository size, build time and first-request latency, and avoid compounding artifacts.

Does next/image convert images to WebP and AVIF?

It can serve WebP by default and AVIF when you enable it in the images formats configuration. AVIF compresses better but encodes more slowly.

What is the best source image size for Next.js?

Roughly the widest rendered width multiplied by two for high-density screens. A hero shown at 1440 CSS pixels wide needs about 2880 pixels of source at most.

How do I improve LCP with next/image?

Mark the above-the-fold hero image as priority, give it correct width, height and sizes, and make sure the source file is already small.

Should I use unoptimized on next/image?

Only when you have a specific reason, such as pre-generated assets or static export constraints. It sends the source file as-is, so the source must already be optimized.

Can I automate image compression for a Next.js project?

Yes. A desktop tool with a watch folder, such as TinyPixels, compresses new images locally as they are added, without a build plugin.

Compress Next.js image sources automatically

Download TinyPixels — 100% local, zero uploads, one-time Pro purchase.