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

Php Uglifyjs Laravel Package

gkralik/php-uglifyjs

PHP port of Dean Edwards’ JavaScript Packer for minifying/packing JS. Install via Composer and compress a script with GK\JavascriptPacker->pack(), choosing encoding (0/10/62/95), optional fast decoder, and special chars handling.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require gkralik/php-uglifyjs
    

    Add to require-dev if only needed for local development or testing.

  2. First Use Case: Minify a JavaScript string or file in a Laravel controller or Blade template:

    use GK\JavascriptPacker;
    
    // Minify a string
    $script = 'console.log("Hello");';
    $packer = new JavascriptPacker($script);
    $minified = $packer->pack();
    
    // Minify a file
    $filePath = public_path('js/custom.js');
    $jsContent = file_get_contents($filePath);
    $minified = (new JavascriptPacker($jsContent))->pack();
    file_put_contents($filePath, $minified);
    
  3. Where to Look First:

    • Constructor Parameters: Focus on $encoding (e.g., 62 for balanced compression) and $fastDecode (set false if decoder bloat is a concern).
    • Default Values: Use (new JavascriptPacker($script))->pack() for quick tests.
    • Encoding Guide: Refer to Dean Edwards' Packer docs for encoding level trade-offs (e.g., 95 for maximum compression but larger output).

Implementation Patterns

1. Blade Directives for Inline JS

Create a custom Blade directive to minify JS snippets dynamically:

// app/Providers/BladeServiceProvider.php
use Illuminate\Support\Facades\Blade;
use GK\JavascriptPacker;

public function boot()
{
    Blade::directive('packJs', function ($expression) {
        return "<?php echo (new GK\\JavascriptPacker({$expression}))->pack(); ?>";
    });
}

Usage in Blade:

@packJs($scriptVariable)

2. Service Provider for Reusability

Register the packer as a singleton in AppServiceProvider:

public function register()
{
    $this->app->singleton('jsPacker', function () {
        return new JavascriptPacker('', 62, true, false); // Default config
    });
}

Usage:

$minified = app('jsPacker')->pack($yourScript);

3. Middleware for API Responses

Compress JS payloads in API responses (e.g., for SPAs or dynamic JS):

// app/Http/Middleware/CompressJsMiddleware.php
public function handle($request, Closure $next)
{
    $response = $next($request);
    if ($response->headers->get('Content-Type') === 'application/javascript') {
        $response->setContent(app('jsPacker')->pack($response->getContent()));
    }
    return $response;
}

Register in app/Http/Kernel.php:

protected $middleware = [
    // ...
    \App\Http\Middleware\CompressJsMiddleware::class,
];

4. Laravel Mix Integration

Use the package as a custom Webpack loader (advanced):

// webpack.mix.js
const UglifyJS = require('gkralik/php-uglifyjs').default;

mix.webpackConfig({
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'raw-loader',
                    options: {
                        esModule: false,
                        minimize: (content) => {
                            return new UglifyJS(content, 62, true, false).pack();
                        }
                    }
                }
            }
        ]
    }
});

Note: Requires Node.js and may not work directly; use as a fallback for PHP-only environments.

5. Queue Jobs for Large Scripts

Offload compression for CPU-intensive tasks (e.g., admin dashboards):

// app/Jobs/CompressJsJob.php
public function handle()
{
    $script = file_get_contents(storage_path('js/large-script.js'));
    $minified = (new JavascriptPacker($script, 95))->pack();
    file_put_contents(storage_path('js/large-script.min.js'), $minified);
}

Dispatch in a controller:

CompressJsJob::dispatch()->onQueue('compression');

6. Dynamic JS in Blade

Minify JS generated dynamically (e.g., for user-specific scripts):

// Controller
public function getUserScript()
{
    $script = "var userId = {$this->user->id}; // ...";
    return response($script)->header('Content-Type', 'application/javascript');
}

Middleware (as shown above) can auto-compress this.


Gotchas and Tips

Pitfalls

  1. ES6+ Incompatibility:

    • Issue: Fails on const, let, arrow functions, template literals, etc.
    • Fix: Transpile to ES5 first using Babel or Laravel Mix’s @babel/preset-env.
    • Workaround: Use try-catch to fallback to original:
      try {
          return app('jsPacker')->pack($script);
      } catch (\Exception $e) {
          return $script; // Fallback
      }
      
  2. Encoding Level Trade-offs:

    • 0 (None): No compression, but smallest output size (includes decoder).
    • 62 (Normal): Balanced (default). Use for most cases.
    • 95 (High ASCII): Maximum compression but largest output (includes decoder).
    • Tip: Test with 62 first; switch to 95 only if file size is critical.
  3. Decoder Bloat:

    • Issue: $fastDecode=true (default) adds a decoder to the output, increasing size.
    • Fix: Set $fastDecode=false if decoder isn’t needed (e.g., for static assets).
  4. Special Characters Flag:

    • Issue: $specialChars=true breaks if JS uses non-standard variable names (e.g., var 1var = 1;).
    • Fix: Keep false unless you’ve explicitly flagged private variables.
  5. Performance Overhead:

    • Issue: Compression is CPU-intensive. Avoid on high-traffic routes.
    • Fix:
      • Cache compressed JS (Redis/Memcached).
      • Use queue jobs for large scripts.
      • Benchmark with hirenwood/laravel-debugbar:
        \Debugbar::info('JS Compression Time', microtime(true) - $start);
        
  6. XSS Risks:

    • Issue: Packing untrusted JS may expose vulnerabilities (e.g., eval injection).
    • Fix: Sanitize input or restrict usage to trusted scripts.
  7. Unmaintained Package:

    • Issue: Last update in 2016; no security patches.
    • Fix:
      • Fork the repo for critical fixes.
      • Monitor for PHP version compatibility (e.g., declare(strict_types=1)).

Debugging Tips

  1. Validate Input: Check for malformed JS before packing:

    if (!is_string($script) || empty(trim($script))) {
        throw new \InvalidArgumentException('Invalid JS script');
    }
    
  2. Log Errors: Wrap pack() calls to log failures:

    try {
        $minified = app('jsPacker')->pack($script);
    } catch (\Exception $e) {
        \Log::error("JS Compression Failed: {$e->getMessage()}", ['script' => substr($script, 0, 100)]);
        $minified = $script; // Fallback
    }
    
  3. Compare Outputs: Use diff to compare minified vs. original:

    diff <(echo "$original") <(echo "$minified") | wc -l
    
  4. Test Edge Cases:

    • Empty strings.
    • Scripts with syntax errors (should not crash).
    • Very large scripts (test memory limits).

Extension Points

  1. Custom Encoding Strategies: Extend the packer to support additional encoding levels:

    class CustomPacker extends JavascriptPacker {
        public function packWithCustomEncoding($script) {
            return parent::pack($script, 'CustomLevel');
        }
    }
    
  2. Pre/Post-Processing: Chain with other tools (e.g., remove comments first):

    $script = preg_replace('/\/\/.*|\/\*[\s\S]*?\*\//', '', $script);
    $minified = app('jsPacker')->pack($script);
    
  3. Caching Layer: Add Redis caching to avoid reprocessing:

    $cacheKey = 'js:minified
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours