Plugins

Image Compressor

Automatically compress images before upload to reduce file size and bandwidth.

Image Compressor

The PluginImageCompressor automatically compresses images before upload, reducing file sizes while maintaining visual quality.

Usage

// Via options (recommended)
const uploader = useUploadKit({
  imageCompression: true, // Enable with defaults
})

// With custom options
const uploader = useUploadKit({
  imageCompression: {
    maxWidth: 1920,
    maxHeight: 1920,
    quality: 0.85,
    outputFormat: "webp",
  },
})

// Via plugin directly
import { PluginImageCompressor } from "nuxt-upload-kit"

const uploader = useUploadKit({
  plugins: [
    PluginImageCompressor({
      maxWidth: 2048,
      quality: 0.8,
    }),
  ],
})

Options

OptionTypeDefaultDescription
maxWidthnumber1920Maximum width in pixels
maxHeightnumber1920Maximum height in pixels
qualitynumber0.85JPEG/WebP quality (0-1)
outputFormat'jpeg' | 'webp' | 'png' | 'auto''auto'Output format
minSizeToCompressnumber100000Minimum size to trigger compression (bytes)
preserveMetadatabooleantruePreserve EXIF metadata

How It Works

  1. Check eligibility - Only compresses images above minSizeToCompress
  2. Load image - Creates an in-memory image element
  3. Resize if needed - Scales down if larger than maxWidth/maxHeight
  4. Compress - Re-encodes at specified quality
  5. Compare sizes - Only uses compressed version if smaller

Skipped Files

The compressor automatically skips:

  • Non-image files
  • GIF files (to preserve animation)
  • SVG files (already optimized vectors)
  • Files smaller than minSizeToCompress
  • Remote files (no local data)

Events

Listen to compression events for progress feedback:

// Compression started
uploader.on("image-compressor:start", ({ file, originalSize }) => {
  console.log(`Compressing ${file.name} (${(originalSize / 1024).toFixed(1)} KB)`)
})

// Compression completed
uploader.on("image-compressor:complete", ({ file, originalSize, compressedSize, savedBytes }) => {
  const savings = ((savedBytes / originalSize) * 100).toFixed(1)
  console.log(`Compressed ${file.name}: saved ${(savedBytes / 1024).toFixed(1)} KB (${savings}%)`)
})

// Compression skipped
uploader.on("image-compressor:skip", ({ file, reason }) => {
  console.log(`Skipped ${file.name}: ${reason}`)
})

Output Formats

Auto (Default)

Preserves the original format:

imageCompression: {
  outputFormat: "auto" // JPEG stays JPEG, PNG stays PNG
}

WebP

Modern format with excellent compression:

imageCompression: {
  outputFormat: 'webp',
  quality: 0.85 // WebP quality
}

JPEG

Best for photographs:

imageCompression: {
  outputFormat: 'jpeg',
  quality: 0.85
}

PNG

Lossless, best for graphics with transparency:

imageCompression: {
  outputFormat: "png"
  // quality is ignored for PNG
}

Quality Guide

QualityUse CaseFile Size
0.95Professional photographyLarger
0.85General purpose (default)Balanced
0.75Web thumbnailsSmaller
0.60Maximum compressionSmallest

Metadata

After compression, files include metadata:

file.meta.compressed // true if compressed
file.meta.originalSize // Original size in bytes
file.meta.compressionRatio // e.g., "45.2" (percent saved)

Example: Show Compression Stats

<script setup>
const uploader = useUploadKit({
  imageCompression: { quality: 0.8 },
})

const compressionStats = ref({ totalSaved: 0, filesCompressed: 0 })

uploader.on("image-compressor:complete", ({ savedBytes }) => {
  compressionStats.value.totalSaved += savedBytes
  compressionStats.value.filesCompressed++
})
</script>

<template>
  <div v-if="compressionStats.filesCompressed > 0">
    Compressed {{ compressionStats.filesCompressed }} images, saved
    {{ (compressionStats.totalSaved / 1024 / 1024).toFixed(2) }} MB
  </div>
</template>

Example: Conditional Compression

// Only compress large images
const uploader = useUploadKit({
  imageCompression: {
    minSizeToCompress: 500 * 1024, // Only compress files > 500KB
    quality: 0.8,
  },
})

Browser Support

Image compression uses the Canvas API, supported in all modern browsers. The compressor gracefully handles failures by keeping the original file.

Copyright © 2026