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

Js Compress Laravel Package

wyrihaximus/js-compress

Compress and minify JavaScript in PHP with wyrihaximus/js-compress, a small library that wraps a JS compressor behind a simple API so you can shrink assets during your build or at runtime.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and confirm the runtime dependency first. composer require wyrihaximus/js-compress only installs the PHP side; this package is a thin wrapper around an external js-compress binary driven through symfony/process. Before writing any code, open the package README and composer.json and check whether the binary is bundled, downloaded by a Composer script, or expected on PATH. Then verify with which js-compress (or the path the README documents) inside the same container/CI image that runs your app.
  2. Where to look first. Read vendor/wyrihaximus/js-compress/src/ — the public surface is small, usually a single Compressor class (implementing a CompressorInterface from a companion wyrihaximus/compress abstraction) exposing compress(string $js): string. Skim its tests: they're the fastest way to see exactly what input the binary receives and whether it shells out per call, writes temp files, or streams via stdin.
  3. Smoke test in Tinker. Run app(\WyriHaximus\JsCompress\Compressor::class)->compress("function add(a, b) {\n return a + b;\n}") and confirm you get back a single line. If that throws, the problem is the binary, not your code — fix that before building anything on top.
  4. Pick the right first use case. For a normal Laravel app, Vite (or Mix) already minifies your bundles, so don't reinvent that. The realistic day-one use case is dynamic or non-bundled JavaScript: snippets stored in the database, @if-gated inline scripts emitted by a Blade component, or vendor JS files copied into public/ that your build pipeline never touches. Start there — a small Artisan command that minifies one file to *.min.js is the cheapest proof of value.

Implementation Patterns

Container binding + interface injection. Don't new Compressor() inline. Bind the interface as a singleton in a service provider so you can swap it for a no-op in tests:

$this->app->singleton(\WyriHaximus\Compress\CompressorInterface::class, fn () => new \WyriHaximus\JsCompress\Compressor());

Build-step command, not request-time. The natural home for this is a console command run from composer.json scripts or your deploy pipeline:

foreach (File::glob(public_path('js/vendor/*.js')) as $path) {
    File::put(
        preg_replace('/\.js$/', '.min.js', $path),
        $this->compressor->compress(File::get($path))
    );
}

Wire it as php artisan js:compress and call it in the post-autoload-dump or your CI "build" step, next to npm run build. Keeping it out of the request lifecycle avoids paying a process-spawn per pageview.

Cache aggressively by content hash. If you must minify at runtime (DB-stored snippets, CMS-authored JS), never do it twice for the same input:

$minified = Cache::remember(
    'js.min.'.hash('xxh128', $source),
    now()->addDay(),
    fn () => $this->compressor->compress($source)
);

Content-hash keys mean edits invalidate naturally, and you get a free record of which snippets are actually hot.

A Blade component for inline scripts. Encapsulate minification in a <x-inline-js :code="$snippet" /> component that no-ops outside production (app()->isProduction()) and otherwise pipes through the compressor. This keeps debug-friendly output locally and terse output in prod without scattering conditionals through templates.

Batch large sets via a job. If you're minifying hundreds of vendor files, dispatch a queued job (or Bus::batch) so the deploy isn't blocked and a single failure is retryable and isolated.

Response macro for one-off routes. For routes that serve a generated .js file (feature flags, config blobs), a Response::macro('js', ...) that sets Content-Type: application/javascript and runs the compressor on the payload is tidier than a controller method per file — but only if you can cache it, per the note above.

Gotchas and Tips

  • It is not pure PHP. The most common failure mode is a green local composer install and a hard failure in production or CI because the binary isn't in the image. Bake it into your Dockerfile and pin the version; add a php artisan js:compress --check style preflight that exits non-zero when the binary is missing so deploys fail loudly instead of silently shipping unminified code.
  • Process spawn cost dominates. Each compress() call forks a process. That's ~10–100ms of overhead before any actual work — fine for a build step, ruinous inside a loop on a hot route. Batch inputs, or push to a queue.
  • Dialect mismatch is silent-ish but real. JS minifiers vary in ES support. Modern syntax (optional chaining, class fields, top-level await) may throw or, worse, be mangled. Test with your actual app JS, and keep the compressor in a "fail the build" mode rather than a try/catch-and-ship-original fallback — corrupt JS is harder to debug than a failed build.
  • No source maps. Debug minification problems locally against the unminified source; only invoke the compressor when app()->isProduction() or during the build, otherwise you'll be reading stack traces pointing at line 1, column 4000.
  • Don't double-minify. Vendor .min.js files are already compressed; running them through again wastes time and occasionally breaks regex-heavy code. Filter on file name in your glob.
  • Watch whitespace and empty input. Passing an empty string or a comment-only file can produce an empty result or an exception depending on the binary; guard with blank($js) before calling, and assert in a test that an empty input returns an empty string rather than blowing up a deploy.
  • Windows/CI path quirks. The process wrapper needs a resolvable path; on Windows runners you may need the explicit .cmd/.exe and a forward-slash-normalised path. This is a common reason the package "works on my machine."
  • Extension point: swap the compressor. Because you bound CompressorInterface, you can drop in a Terser or esbuild-backed implementation (shelling out to npx) without touching call sites — worth doing if the packaged binary lags on modern syntax. Likewise, bind a FakeCompressor returning input unchanged in your test suite so tests stay fast and don't require the binary.
  • Test the contract, not the output. Assertions like "output contains no // comments" or "output is shorter than input" are stable; exact-string assertions on minified output will break on every binary bump.
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels