Bu makale, HTML to Image blogunda yayınlanmış olan orijinal makaleden alınmıştır.
Browsershot, Laravel geliştiricilerinin HTML’i bir görüntüye dönüştürmek istediklerinde başvurduğu pakettir. Puppeteer’ı sarar, gerçek Chrome’u çalıştırır ve piksel bazında doğru çıktı üretir. Geliştirici makinenizde ilk işleyişte düzgün çalışır. Ancak dağıttığınızda, ilk render sırasında Failed to launch the browser process! hatası alırsınız.
Burada sorun, Browsershot’ın kodundan ziyade çalıştığı makineden kaynaklanmaktadır.
Browsershot’ın sunucunuzdan talep ettikleri
Browsershot, içinde ikinci bir çalışma zamanı saklayan bir PHP paketidir. Üretim ortamında çalıştırmak için Node.js, Puppeteer npm paketi, bir Chrome veya Chromium binary’si ve Chrome ile bağlantılı olan paylaşılan kütüphanelerin uzun kuyruklarına (örneğin libnss3, libatk, libgbm) ve şablonlarınızı kapsayacak kadar geniş bir font setine ihtiyacınız vardır, emoji dahil.
Bu, kontrol ettiğiniz tam bir VPS’de yönetilebilir. Ancak Laravel uygulamalarının giderek daha fazla çalıştığı yerlerde işler bozuluyor:
- Laravel Vapor ve sunucusuz. PHP Lambda çalışma zamanı ne Node ne de Chrome ile birlikte gelir ve Lambda üzerinde apt-get ile ilerleyemezsiniz. Lambda üzerindeki Puppeteer kılavuzu, bu konunun ne kadar derin olduğunu anlatmaktadır.
- Paylaşımlı ve yönetilen hosting. Root yok, sistem paketleri yok, tarayıcı binary’si yok. Browsershot sadece masada yer almıyor.
- Minimal Docker imajları.
php:8.3-fpm-alpine, Chrome’un bağımlılıklarını içermez. Chromium, kütüphaneleri ve fontları eklemek birkaç yüz megabayt yer kaplar ve Dockerfile’ınızda sürekli bir bakım hattı gerektirir. - CI hatları, her iş teslimatınızdan önce bir tarayıcı indirmenin zorunda olduğu durumlarda.
Bağımlılık da burada sona ermez. Spatie’nin daha yeni paketleri bile bunu miras alır: spatie/laravel-og-image, laravel-screenshot aracılığıyla render alır, bu da Node ve Chrome gereksinimlerinin tüm aileyi takip etmesini sağlar.
Yaygın yöntemler
İlk geçici çözüm, kalın bir konteynır oluşturmaktır: Chromium, kütüphaneler ve bir font yığını imajınıza eklenir, sandbox bayrakları verilerek boyut kabul edilir. Çalışır, ancak her render aynı makinede çalışan bir Chrome sürecini başlatır. Chrome açgözlüdür, bu nedenle bellek bütçeniz ve render eş zamanlılığınız aniden aynı bütçeye dönüşür; OG görüntüleri için tetiklenen bir trafik patlaması PHP-FPM’i düşürebilir.
İkinci çözüm, yan hizmettir: wnx/sidecar-browsershot, Browsershot’u özel bir Node Lambda’ya taşır, böylece Vapor uygulamanız onu çağırabilir. Gerçekten akıllıca bir çözüm ve sunucusuz durumu çözüyor. Ancak bu ayrıca, kendi IAM rolleri, katmanları, soğuk başlatmaları ve PHP kodunuza sıkı bir şekilde bağlı kalması gereken bir Node işlevi olan ikinci bir dağıtım sahibi olmanız anlamına gelir.
Her iki yöntem de gerçek çözümler. Ancak ikisi de uygulamanızın bir PNG üretmesi için bir tarayıcı filosu işletme anlamına gelir.
Üçüncü seçenek, tarayıcıyı barındırmayı bırakmaktır.
API Üzerinden Render Alma
HTML’den görüntüye resim dönüştürmek için resmi Laravel paketi, Chrome’un kısmını bir API gerisine alır ve uygulamanızla tek bir HTTP çağrısı bırakır. Bu GitHub ve Packagist‘de bulunmaktadır; kurulum, yükleme ve bir anahtar gerektirir:
composer require html2img/html2img-laravel
HTML2IMG_API_KEY=your-api-key
Paket keşfi, hizmet sağlayıcısını ve Html2img facadesını kaydeder; php artisan html2img:test çalıştırarak anahtarın aktif olduğunu onaylamak için küçük bir test resmi oluşturur. Renderlar hala gerçek Chrome’da çalışır, sadece API tarafında, bu nedenle flexbox, grid, özel özellikler, web fontları ve çevrimiçi JavaScript, Browsershot altındaki gibi davranır. Çıktıda bir değişiklik yoktur, sadece Chrome’un konumu değişmiştir.
Örnek bir durum, bir Blade görünümünden render edilen bir dinamik Open Graph resmi dir:
use Html2img\Laravel\Facades\Html2img;
use Html2img\Request\HtmlRequest;
$response = Html2img::html(new HtmlRequest(
html: view('og.post', [=> $post])->render(),
width: 1200,
height: 630,
dpi: 2, // retina
));
return $response->url; // https://i.html2img.com/abc123def456.png
Sunucuda Node yok, ayarlanacak binary yollar yok, Dockerfile’da hiçbiri yok. Aynı çağrı, Blade görünümlerinin üretebileceği her şeyi renderlar; fatura görüntüsüne ilişkin rehber, kapsamlı bir faturalama örneğini göstermektedir. Paket rehberi, konfigürasyon dosyasını, özel Guzzle istemci bağlama işlemine ve her render seçeneğine ilişkin bilgileri kapsar.
Çağrı noktasını değiştirme
Migration işlemi çoğunlukla mekaniktir çünkü şekiller hizalanır. Tipik bir Browsershot çağrısı:
use Spatie\Browsershot\Browsershot;
Browsershot::html(view(, [=> ])->render())
->windowSize(1200, 630)
->save(storage_path({->}));
şu hale gelir:
use Html2img\Laravel\Facades\Html2img;
use Html2img\Request\HtmlRequest;
$response = Html2img::html(new HtmlRequest(
: ('og.post', ['post' => $post]) ->renderwidth1200height630));
$path = Html2img::storeEkran görüntüleri de destekleniyor
Browsershot’ın diğer bir görevi canlı URL’leri yakalamaktır ve geçiş aynı şekildedir. selector yakalamayı bir öğeye keserken, css yakalamadan önce enjekte edilir ve bu, resimden çerez banner’ları ve sohbet kutularını kaldırmanın nazik yoludur:
use Html2img\Laravel\Facades\Html2img;
use Html2img\Request\ScreenshotRequest;
$response = Html2img::screenshot(new ScreenshotRequest(
: ,
: ,
:
: ,
selector parametre belgeleri kesme davranışını kapsar, ayrıca bir URL’den tek bir öğenin ekran görüntüsünü almanın tam yürütmesi üzerinden geçer.
Gerçekten yakalayabileceğiniz hata işleme
Browsershot hataları, süreç istisnaları olarak yüzeye çıkar; bu, Chrome’un çöktüğünü, zaman aştığını veya hiç başlatılmadığını anlamak için stderr dizelerine eşleşmeniz gerektiği anlamına gelir. Paket, duruma bağlı olarak hataları tespit eder; tiplenmiş istisnalar fırlatılır:
use Html2img\Laravel\Facades\Html2img;
use Html2img\Request\HtmlRequest;
use Html2img\Exception\RateLimitException;
use Html2img\Exception\Html2imgException;
try {
$response = Html2img::html(new HtmlRequest(: ));
} catch (RateLimitException ) {
// 429: geri off ve işin tekrar edilmesi için serbest bırak
} catch (Html2imgException ) {
report(); // durum kodu, hata kodu ve yük tümü bir arada
}
Bu ayrım, kuyruklanmış işlerde en önemli noktadır; burada render işlemi doğal bir uyum sağlar. handle() fonksiyonuna Html2img\Laravel\Html2img tipini yazın ve konteyner yapılandırılmış yöneticiyi enjekte eder; facade gerekli değildir.
Browsershot’ın hâlâ doğru çağrı olduğu durumlar
Bir API her şeyin cevabı değildir; aksi düşünmek yanıltıcı olur.
Uygunluk kurallarınız, markup’ı harici bir hizmete göndermeyi yasaklıyorsa, tarayıcıyı tamamen kontrol etmeniz gerekir. İş akışınız görüntü yerine PDF üretiyorsa, Browsershot, görüntü API’sinin kapsamadığı alanları kapsar. Eğer sürekli olarak, çok yüksek hacimlerde render alıyorsanız ve bir operasyon ekip Chrome filoda beslemekten mutluyken, izolasyona dayalı altyapı render başına maliyeti aşabilir. Puppeteer karşılaştırması bu trade-off’u açık bir şekilde sergiliyor.
Diğer herkes için, sunucunuzda Chrome bulundurmak bir vergi gibidir. Bu; Dockerfile satırları, bellek kapasitesi, 2’de bir sayfa görüntüsü ve her ortamda binary’nin sizi takip edemediği zamanlarda ödenmesini gerektirir. Bir composer paketi ve bir API anahtarı, başkalarının sorununu çözmenizi sağlar; ve o kişi Chrome’u profesyonel olarak çalıştırır.
Eğer sunucunuzda Chrome’u tutan tek sebep görüntü render’ıysa, şablon galerisine göz atın veya belgeleri okuyun , harekete geçin.
Browsershot’ı çalıştırmak için bir sunucu ile mücadele ettiyseniz, Vapor, paylaşımlı hosting veya ince bir konteyner üzerine deneyimlerinizi yorum kısmında paylaşın.
Kaynak: Orijinal Makale


