spatie/image-optimizer
Optimize PNG, JPG, WebP, AVIF, SVG and GIF images in PHP by running them through a chain of installed binaries (jpegoptim, optipng, pngquant, svgo, etc.). Automatically detects available tools and overwrites files with smaller optimized versions.
Install the Package
composer require spatie/image-optimizer
For Laravel-specific integration, use:
composer require spatie/laravel-image-optimizer
Install Optimization Tools Choose your OS and run the relevant commands from the README. Example for Ubuntu/Debian:
sudo apt-get install jpegoptim optipng pngquant gifsicle webp libavif-bin
npm install -g svgo
First Use Case Optimize an image in-place:
use Spatie\ImageOptimizer\OptimizerChainFactory;
$optimizer = OptimizerChainFactory::create();
$optimizer->optimize(storage_path('app/public/image.jpg'));
src/Optimizers/ for built-in tools and their configurations.Basic Optimization
$optimizer = OptimizerChainFactory::create();
$optimizer->optimize($inputPath, $outputPath); // Overwrite or save to new path
Batch Processing
Use Laravel's Storage facade or collect() to process multiple files:
$files = Storage::files('public/images');
foreach ($files as $file) {
$optimizer->optimize($file);
}
Queue Optimization Jobs For large-scale processing, dispatch jobs:
use Spatie\ImageOptimizer\Jobs\OptimizeImage;
OptimizeImage::dispatch($imagePath)->onQueue('optimize');
Custom Chains Override default optimizers for specific needs:
$chain = (new OptimizerChain)
->addOptimizer(new Jpegoptim(['--strip-all', '--max=90']))
->addOptimizer(new Pngquant(['--force', '--speed=1']));
$chain->optimize($path);
Storage::disk('public')->put() to save optimized files.use Spatie\ImageOptimizer\OptimizerChainFactory;
class OptimizeCommand extends Command {
protected $signature = 'images:optimize {path}';
public function handle() {
$optimizer = OptimizerChainFactory::create();
$optimizer->optimize($this->argument('path'));
}
}
use Spatie\ImageOptimizer\OptimizerChainFactory;
class HandleUpload {
public function handle() {
$optimizer = OptimizerChainFactory::create();
$optimizer->optimize($uploadedFilePath);
}
}
Missing Binaries
$PATH. Use which jpegoptim (Linux/Mac) or check where jpegoptim (Windows).$optimizer->useLogger(new \Monolog\Logger('optimizer', [new \Monolog\Handler\StreamHandler(storage_path('logs/optimizer.log'))]));
Permission Issues
www-data, nginx) has write permissions:
chmod -R 755 storage/app/public
chown -R www-data:www-data storage/app/public
SVGO Breaking SVGs
$optimizerChain->addOptimizer(new Svgo(['--config', __DIR__.'/svgo.config.js']));
Timeouts
$optimizer->setTimeout(30); // 30 seconds per optimizer
$optimizerChain->setBinaryPath('jpegoptim', '/custom/path/jpegoptim');
$optimizer->useLogger(new class implements \Psr\Log\LoggerInterface {
public function log($level, $message, array $context = []) {
dump($message); // Inspect commands
}
// ... other required methods
});
flock or queues).Custom Optimizers
Implement the Optimizer interface for new tools (e.g., Guetzli for JPEG):
class GuetzliOptimizer implements Optimizer {
public function binaryName(): string { return 'cjpeg -guetzli'; }
public function canHandle(Image $image): bool { return $image->isJpeg(); }
// ... other methods
}
Pre/Post-Processing Chain optimizers with Laravel events or middleware:
event(new OptimizedImage($originalPath, $optimizedPath));
Progress Tracking
Use Laravel's ProgressBar for batch jobs:
$bar = new ProgressBar($files->count());
foreach ($files as $file) {
$optimizer->optimize($file);
$bar->advance();
}
\Spatie\ImageOptimizer\OptimizerChain::forgetCachedBinaries();
jpegoptim vs JpegOptim). Use lowercase in configs.How can I help you explore Laravel packages today?