Weave Code
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

Sidecar Browsershot Laravel Package

wnx/sidecar-browsershot

Run Spatie Browsershot on AWS Lambda via Sidecar in Laravel. Generate PDFs/screenshots without installing Node, Puppeteer, or Chrome on your server—headless Chrome runs in a deployed Lambda function. Includes config publishing and Sidecar deploy workflow.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require wnx/sidecar-browsershot
    

    Ensure your Laravel app is configured for Sidecar (check sidecar.php config).

  2. Basic Usage Register the Browsershot Sidecar function in app/Providers/SidecarServiceProvider.php:

    public function registerFunctions()
    {
        return [
            \Wnx\SidecarBrowsershot\Functions\Browsershot::class,
        ];
    }
    
  3. First Lambda Invocation Use the sidecar facade to trigger Browsershot:

    use Wnx\Sidecar\Facades\Sidecar;
    
    $html = '<h1>Hello, Browsershot!</h1>';
    $path = Sidecar::call('browsershot', [
        'html' => $html,
        'filename' => 'output.png',
    ]);
    

Key Files to Review


Implementation Patterns

Common Workflows

1. PDF Generation

$pdfPath = Sidecar::call('browsershot', [
    'html' => view('invoice')->render(),
    'format' => 'pdf',
    'options' => [
        'margin-top' => '1cm',
        'margin-right' => '1cm',
        'margin-bottom' => '1cm',
        'margin-left' => '1cm',
    ],
]);

2. Dynamic URL Capture

$url = 'https://example.com/blog/post-123';
$imagePath = Sidecar::call('browsershot', [
    'url' => $url,
    'filename' => 'post-123.png',
    'width' => 1200,
    'height' => 630,
]);

3. Queue Integration

Use Laravel Queues to offload heavy rendering:

use Illuminate\Support\Facades\Queue;

Queue::push(function () {
    Sidecar::call('browsershot', [
        'html' => $this->generateComplexReport(),
        'filename' => "report_{$this->reportId}.pdf",
    ]);
});

4. Reusing Sidecar Responses

Cache results or process outputs (e.g., upload to S3):

$result = Sidecar::call('browsershot', [
    'html' => $html,
    'filename' => 'temp.png',
    'returnAs' => 'base64', // Return as base64 string
]);

Storage::disk('s3')->put("images/{$filename}.png", base64_decode($result));

Integration Tips

  • Environment-Specific Config: Override sidecar-browsershot.php in config/ for Lambda-specific settings (e.g., timeout, memory).

    'timeout' => env('AWS_LAMBDA_TIMEOUT', 30), // Seconds
    'memory' => env('AWS_LAMBDA_MEMORY', 1024), // MB
    
  • Error Handling: Wrap calls in try-catch to handle Lambda timeouts or Browsershot failures:

    try {
        $path = Sidecar::call('browsershot', [...]);
    } catch (\Wnx\Sidecar\Exceptions\SidecarException $e) {
        Log::error("Browsershot failed: " . $e->getMessage());
        // Fallback to a static image or retry logic
    }
    
  • Blade Views: Pass Blade views directly:

    $html = view('emails.report', ['data' => $reportData])->render();
    Sidecar::call('browsershot', ['html' => $html, 'format' => 'pdf']);
    

Gotchas and Tips

Pitfalls

  1. Lambda Timeouts:

    • Browsershot may take >15s for complex pages. Configure Lambda with sufficient timeout/memory:
      'timeout' => 60, // Increase if needed
      'memory' => 3008, // 3GB for heavy pages
      
    • Debug: Check CloudWatch logs for Task timed out errors.
  2. Headless Chrome Limits:

    • Lambda’s /tmp is ephemeral (512MB–10GB). Large outputs may fail.
    • Fix: Use returnAs => 'base64' to avoid writing to disk, or clean /tmp post-execution:
      // In your Sidecar function (extend Browsershot)
      public function handle()
      {
          $result = parent::handle();
          if (file_exists($this->filename)) {
              unlink($this->filename);
          }
          return $result;
      }
      
  3. CORS/Network Issues:

    • If capturing URLs, ensure Lambda has internet access (VPC/NAT gateway).
    • Test: Use curl in Lambda to verify connectivity:
      exec('curl -I https://example.com', $output, $return);
      
  4. Font/Resource Loading:

    • Remote fonts/styles may fail in Lambda. Use local paths or embed resources:
      $html = '<style>@font-face { src: url("data:font/woff2;base64,...); }</style>';
      

Debugging Tips

  • Local Testing: Use sidecar:test to simulate Lambda locally:

    php artisan sidecar:test browsershot --html="<h1>Test</h1>"
    
  • Logging: Enable Sidecar logging in sidecar.php:

    'logging' => [
        'enabled' => true,
        'channel' => 'single',
    ],
    
  • Common Errors:

    Error Cause Solution
    Failed to execute process Missing Chrome binary Ensure Lambda layer has Chrome installed.
    Connection refused Port 3000 not exposed Use puppeteer-executable-path config.
    ENOSPC Disk full (/tmp) Increase Lambda ephemeral storage.
    TimeoutException Slow page load Increase timeout or optimize HTML.

Extension Points

  1. Custom Headless Chrome Flags: Extend the Browsershot function to pass flags:

    // In your Sidecar function
    protected function getChromeFlags(): array
    {
        return [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage', // Bypass `/dev/shm` limits
            '--disable-gpu',
        ];
    }
    
  2. Post-Processing: Chain Sidecar functions for multi-step workflows:

    $pdfPath = Sidecar::call('browsershot', ['html' => $html, 'format' => 'pdf']);
    $optimizedPath = Sidecar::call('optimize-pdf', ['file' => $pdfPath]);
    
  3. Shared Storage: Mount an EFS volume to Lambda for persistent storage of Chrome binaries or caches:

    // sidecar-browsershot.php
    'chrome_binary_path' => '/mnt/efs/chrome-linux/chrome',
    
  4. Retry Logic: Implement exponential backoff for transient failures:

    use Wnx\Sidecar\Facades\Sidecar;
    
    $maxRetries = 3;
    $retryDelay = 1000; // ms
    
    for ($i = 0; $i < $maxRetries; $i++) {
        try {
            return Sidecar::call('browsershot', [...]);
        } catch (\Exception $e) {
            if ($i === $maxRetries - 1) throw $e;
            usleep($retryDelay * (2 ** $i));
        }
    }
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests