Batch Image Compression for Web Developers | Bulk Image Compressor

Images are the heaviest assets on most websites. On an average page, they account for 40 to 60% of total weight. If you’re a web developer and you’re not compressing images, you’re shipping bloated pages no matter how clean your code is.

The question isn’t whether to compress. It’s where in your workflow compression should happen and which tool fits each situation.

Where image compression fits in a dev workflow

There are three main points where you can compress images during development:

Before commit. You optimize images locally before they ever enter version control. This keeps your repository lean and means every environment (staging, production, other developers’ machines) gets the optimized versions automatically.

During build. Build tools like Vite or webpack handle compression as part of the asset pipeline. Source images stay at full quality in the repo, and the build process generates optimized versions for deployment.

At the CDN layer. Services like Cloudflare, Imgix, or Cloudinary transform and compress images on the fly based on the requesting device and browser.

Each approach has tradeoffs, and you can combine them.

Online tools vs build plugins

For a quick one-off task, like compressing a batch of screenshots for a blog post or optimizing a set of icons, an online tool is the fastest option. Open Bulk Image Compressor, drop your files in, adjust quality, and download. Done in under a minute.

Build plugins handle ongoing optimization automatically. Here’s what that looks like in practice.

Vite

Vite users can use vite-plugin-imagemin or similar plugins:

// vite.config.js
import imagemin from 'vite-plugin-imagemin';

export default {
  plugins: [
    imagemin({
      mozjpeg: { quality: 80 },
      webp: { quality: 80 },
      pngquant: { quality: [0.7, 0.8] },
    }),
  ],
};

This compresses images during vite build. Source files stay untouched. The output directory gets the optimized versions.

webpack

With webpack, image-minimizer-webpack-plugin does the same job:

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.sharpMinify,
          options: {
            encodeOptions: {
              jpeg: { quality: 80 },
              webp: { quality: 80 },
            },
          },
        },
      }),
    ],
  },
};

When to use which

Use an online tool when:

  • You’re adding a handful of images to a project and want them optimized right now
  • You’re working with content from a client or designer who sent unoptimized files
  • Your project doesn’t have a build step (static HTML, simple sites)
  • You want to check compression results visually before committing

Use build plugins when:

  • Your project already has a build pipeline
  • Multiple developers contribute images and you want consistent optimization
  • You need format conversion (e.g., generating WebP versions automatically)
  • You want source images at full quality in the repo for potential future re-processing

CI/CD image optimization

Build plugins run during local builds, but you can also add image optimization to your CI/CD pipeline. This catches unoptimized images that slip through, regardless of who committed them.

A simple approach is running a script in your CI pipeline that checks image file sizes:

# Fail the build if any image is larger than 500KB
find public/images -type f \( -name "*.jpg" -o -name "*.png" -o -name "*.webp" \) -size +500k | tee oversized.txt
if [ -s oversized.txt ]; then
  echo "Found oversized images. Compress before deploying."
  exit 1
fi

For automated compression in CI, tools like sharp-cli or imagemin-cli can process images as a build step. This guarantees that nothing goes to production uncompressed.

Lazy loading and responsive images

Compression alone isn’t enough. How you load images matters just as much.

Lazy loading defers off-screen images until the user scrolls to them. Add loading="lazy" to every image below the fold. Don’t lazy load your hero image or any content that’s visible on initial page load, since that will hurt your Largest Contentful Paint score.

Responsive images serve different sizes based on screen width. A phone doesn’t need a 2400px image intended for a desktop monitor. Use srcset and sizes attributes to let the browser pick the right version:

<img
  src="product-800.webp"
  srcset="product-400.webp 400w, product-800.webp 800w, product-1600.webp 1600w"
  sizes="(max-width: 640px) 400px, (max-width: 1024px) 800px, 1600px"
  alt="Product photo"
  width="1600"
  height="1067"
  loading="lazy"
>

Generate these size variants as part of your build process or with a batch tool before uploading.

CDN delivery

A CDN (Content Delivery Network) serves images from servers geographically close to your visitors. This reduces latency, but some CDNs go further with on-the-fly image optimization.

Cloudflare Image Resizing can resize and convert images to WebP or AVIF automatically based on the visitor’s browser. You don’t need to generate variants yourself.

Imgix and Cloudinary are dedicated image CDNs. You upload one high-quality source, and they generate whatever size, format, and quality you request via URL parameters. This is powerful but adds a per-image cost.

For most projects, compressing images before upload and serving them through a standard CDN (Cloudflare, Fastly, AWS CloudFront) is enough. Dedicated image CDNs make sense when you have thousands of user-uploaded images and need dynamic resizing. For background on why compression matters for the web at all, our guide on why website images need compression covers the fundamentals.

Common mistakes developers make

Committing unoptimized images. A 5MB JPEG in your repo stays there in git history forever, even if you replace it later. Compress before committing.

Using PNG for photographs. PNGs are meant for graphics, screenshots, and images with transparency. A photograph saved as PNG is typically 3 to 5 times larger than the same image as a JPEG or WebP. Use the right format for the content type. Check our format comparison guide for specifics.

Skipping width and height attributes. Without explicit dimensions, the browser doesn’t know how much space to reserve for an image until it loads. This causes layout shifts, which hurts your CLS score and annoys users.

Over-compressing. Pushing quality to 30 or 40% to get tiny files produces visible artifacts. For web images, 75 to 82% quality hits the right balance between size and appearance.

Ignoring image dimensions. Compressing a 4000px photo to 80% quality is good, but if it displays at 600px wide on your page, you’re still sending way more pixels than needed. Resize to your display dimensions first, then compress.

Not using WebP. Browser support for WebP is universal now. If you’re still serving JPEG and PNG exclusively, you’re leaving 25 to 35% file size savings on the table.

A practical approach

For most web projects, here’s what works well:

  1. Resize and compress images before committing, using an online tool like Bulk Image Compressor or a local script.
  2. Add a build plugin as a safety net to catch anything that slipped through.
  3. Use lazy loading and responsive images in your HTML.
  4. Serve through a CDN.

You don’t need to do all four on day one. Start with the first step. That alone will make a noticeable difference in your page load times.

Ready to compress your images?

Bulk compress JPEG, PNG, WebP, and AVIF images right in your browser. No uploads, no sign-ups.

Try Bulk Image Compressor