Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Webp Laravel Package

eyadhamza/laravel-webp

Laravel WebP is a package for converting images to WebP and serving optimized versions in Laravel applications. It helps reduce image file sizes, improve page load performance, and integrate WebP handling into your existing Laravel workflow with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and publish config

    composer require eyadhamza/laravel-webp
    php artisan vendor:publish --tag=laravel-webp
    

    Check composer.json requirements first — the last release was December 2023, so confirm it satisfies your PHP/Laravel constraint before pulling it into a modern app.

  2. Read the README facade/helper signature before writing code. This is a small package (19 stars), so the public surface is narrow. Locate the service provider registration, the facade/helper name, and any Artisan commands it registers with:

    php artisan list | grep -i webp
    
  3. First use case: convert an uploaded image to WebP on the way into storage.

    use Eyadhamza\LaravelWebp\Facades\Webp;
    
    $webpPath = Webp::convert($request->file('image'))
        ->quality(85)
        ->toStorage('public', 'images/hero.webp');
    

    The exact method chain depends on the version — copy the shape from the README and adapt.

  4. Sanity-check your runtime before assuming it works. WebP encoding needs GD compiled with WebP support or Imagick with the WebP delegate:

    php -r "var_dump(function_exists('imagewebp'));"
    php -r "var_dump(imagick::queryFormats('WEBP'));"
    

    If both return false, the package has nothing to encode with — fix the PHP image extension before debugging the package.

Implementation Patterns

Convert-and-store as an upload action. Wrap the package in a small action class so your controllers never depend on the facade directly. This makes it trivial to swap to intervention/image when you outgrow the package.

final class StoreWebpImage
{
    public function __invoke(UploadedFile $file, string $disk = 'public'): string
    {
        $path = 'images/' . Str::uuid() . '.webp';

        Webp::convert($file)->quality(82)->save($disk, $path);

        return $path;
    }
}

Keep the original alongside the WebP. Browsers without WebP support (older Safari on iOS ≤ 13, some email clients) still need a fallback. Store both and serve them via <picture>:

<picture>
    <source srcset="{{ Storage::url("$path.webp") }}" type="image/webp">
    <img src="{{ Storage::url("$path.jpg") }}" alt="{{ $alt }}">
</picture>

Queue the conversion for anything user-facing. WebP encoding of a 4 MB JPEG takes hundreds of milliseconds — do not do it inside the request that accepts the upload.

ProcessImageWebp::dispatch($image->id)->onQueue('images');

In the job, reload the model, resolve the file from the disk, convert, and write a webp_path column. Fire an event when done so the UI can poll or broadcast.

Middleware / route rewrite for content negotiation. If you already have legacy uploads, a middleware that checks Accept: image/webp and transparently swaps the response path is cheaper than retrofitting every model:

if (Str::contains($request>header('Accept'), 'image/webp') && $webp = $this->resolveWebp($path)) {
    return response()->file(Storage::disk('public')->path($webp));
}

Gate it behind a config flag so you can turn it off per environment.

Bulk migration with an Artisan command. For existing media libraries, write a one-off command that iterates models, skips rows where webp_path is already set, and dispatches jobs in chunks. Make it idempotent (updateOrCreate, if (! $exists)) so re-runs are safe.

Blade component or directive. Expose a <x-webp-image :path="$path" :alt="$alt" /> component that emits the <picture> block above. Keeps fallback logic in one place instead of scattered across views.

Gotchas and Tips

  • Package age. Last tagged release is 2023-12-06. Verify against your Laravel version — composer require will tell you immediately, but also read the source before relying on it in production. If it's incompatible, fork it or copy the ~100 lines into your own app/Support directory; a WebP converter is not worth a dependency fight.
  • GD vs Imagick discrepancies. Quality values are not equivalent between drivers. A quality(85) that looks fine under GD can look blocky under Imagick. Pin your driver in config and test with the same extension in staging as in production.
  • Alpha transparency. Naïve JPEG→WebP conversion flattens alpha to white. If you handle PNGs with transparency, check the package's handling of imagealphablending/imagesavealpha; if it doesn't expose it, convert with Imagick directly.
  • MIME type on serving. Return the correct Content-Type: image/webp. Storage::response() sometimes guesses from extension — verify with curl -I that the header is right; a wrong MIME causes the browser to download rather than render.
  • Storage disk config. Most likely the package assumes public or a configured disk. If it writes to storage/app/webp but your public disk symlink points elsewhere, images 404 in production while working locally. Check config/filesystems.php and the package config side by side.
  • Cache busting. If a WebP is regenerated at the same path, browsers and CDNs will serve the stale file. Append a hash or ?v= query param derived from filemtime.
  • Cleanup on delete. Hook the model's deleting event to remove the derived WebP. Without this you accumulate orphans and your disk slowly fills with dead files.
  • Testing. Use Storage::fake('public') in tests and assert the file exists with Storage::disk('public')->assertExists($path). Do not test actual encoding against real fixtures in unit tests — it's slow and driver-dependent; mock the facade instead.
  • Extension points. The package likely lets you override quality, driver, and disk in config. If it lacks a queue/injection point, wrap it — do not edit files under vendor/.
  • Concurrency. Two parallel jobs writing the same target path will race. Use unique filenames per derived asset (UUID or content hash) rather than overwriting in place.
  • Security. Validate uploaded files with Laravel's image rule before handing them to the package; encoding a crafted file through GD has historically been an attack surface.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin