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

Html Minifier Laravel Package

zaininnari/html-minifier

A Laravel/PHP package for minifying HTML output by removing unnecessary whitespace, comments, and redundant markup. It helps reduce response size and improve delivery speed, with simple configuration for adding HTML compression to your application.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm the entry point before writing any integration code — this package is small (61 stars, no linked repo metadata), so treat the source as the source of truth:

composer require zaininnari/html-minifier

Open vendor/zaininnari/html-minifier/src/ and the README first. The package is a PHP port of the Blink HTMLTokenizer used by html-minifier, so the public surface is typically a single minifier class with a minify(string $html): string-style method. Confirm the exact namespace and whether the call is static or instance-based before wiring it in.

The smallest viable use case is minifying already-rendered HTML, not Blade source:

use Zaininnari\HtmlMinifier\HtmlMinifier;

$html = view('welcome')->render();

$minified = (new HtmlMinifier())->minify($html);

return response($minified);

Do not point it at .blade.php files — it will happily strip whitespace inside @if blocks and break directive parsing. It operates on final output only.

First real use case: a response middleware that minifies text/html responses in production. That is the 90% path for Laravel apps and gets you the bandwidth win without touching views.

Implementation Patterns

Response middleware (recommended default). Minify at the edge of the request lifecycle so every controller, package, and error page benefits without per-controller changes:

class MinifyHtml
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        if (! app()->isProduction()) {
            return $response;
        }

        if (! $response instanceof \Illuminate\Http\Response) {
            return $response;
        }

        $contentType = $response->headers->get('Content-Type', '');
        if (! str_contains($contentType, 'text/html')) {
            return $response;
        }

        $content = (new HtmlMinifier())->minify($response->getContent());
        $response->setContent($content);

        return $response;
    }
}

Register it globally but after session/CSRF middleware so you never minify a redirect body or a streamed response.

Response macro for opt-in minification. When global middleware feels too broad, expose an explicit macro and use it on heavy public pages only:

Response::macro('minifiedHtml', function (string $view, array $data = []) {
    return response((new HtmlMinifier())->minify(view($view, $data)->render()));
});

Build-time / cache-time minification. Runtime minification costs CPU on every request. For mostly-static marketing pages, render once, minify once, cache the result in Redis or the filesystem keyed by a content hash, and serve the stored bytes. Invalidate on deploy or when a model changes.

Artisan command for static output. If you pre-render pages (Laravel's route:cache + a crawler, or an SSG step), add a command that walks public/ HTML or a storage/app/prerender/ directory and rewrites files. This keeps the runtime completely free of the minifier.

Config-driven toggles. If the package exposes options (comment removal, whitespace collapsing, attribute quoting), bind them in a config/html-minifier.php you publish or define yourself, and read them in a service provider. Wrap instantiation in a singleton or a small HtmlMinifierFactory so toggling options in one place changes behavior everywhere.

Testing pattern. Never assert exact byte output. Assert semantic equivalence instead: load original and minified into DOMDocument, normalize whitespace-only text nodes, and compare serialized trees. For CSS/JS-in-HTML, additionally assert the extracted <script> and <style> bodies are identical.

Gotchas and Tips

  • Whitespace-sensitive inline content is the #1 breakage. Removing the space between <span>s, <a>s, or <button>s collapses words together. If your design relied on newlines between inline elements as spacing, keep the original whitespace-sensitive regions out of the minifier or fix the CSS (display: inline-block + explicit gap).
  • <pre>, <textarea>, <code>, <script>, <style> must be preserved verbatim. A tokenizer-based minifier can behave differently here than a full DOM parser. Test each of these explicitly — especially <textarea> where leading newlines are meaningful per the HTML spec.
  • Skip non-HTML responses. Guard on Content-Type and short-circuit for BinaryFileResponse, StreamedResponse, JSON, XML, and file downloads. Minifying a PDF or an SVG you serve as image/svg+xml will corrupt or bloat it.
  • Fix Content-Length and ETag. If you or a proxy set these upstream, they must be recalculated or dropped. Laravel's Response usually recalculates on setContent, but Symfony's HTTP cache and reverse proxies can keep stale values.
  • Alpine.js and Vue attribute expressions. x-data, x-text, @click payloads are inside attributes; attribute-value quoting changes can break them. Alpine tolerates whitespace but not stripped quotes around values containing spaces. Verify any custom directive-heavy page.
  • Blade conditional comments. Preserve <!--[if IE]>...<![endif]--> if you still support them; naive comment removal deletes the whole block.
  • Debugging deltas: diff before/after with php -r writing both to files and diff -u, or serve a /__debug/minify route that returns the minified output plus the byte savings. Bisect by disabling the middleware for one route at a time.
  • Performance and memory. The tokenizer reads the whole string into memory. On very large pages (hundreds of KB of HTML) watch memory_limit and keep an eye on response time — benchmark with your heaviest template before enabling globally.
  • License is NOASSERTION. Do not ship this into a commercial product without resolving the actual license from the repository or a Packagist metadata check. Treat it as unlicensed until proven otherwise.
  • Single-maintainer / low-traffic risk. With 61 stars and an unknown upstream repo, pin the exact version in composer.json and consider vendoring or wrapping the minifier behind your own interface so you can swap in voku/html-min or matthiasmullie/minify without touching call sites.
  • Extension points are thin. Expect to extend by composition (your own HtmlMinifierService wrapping the package) rather than subclassing. If you need behavior like preserving specific markers (<!--MINIFIER:OFF-->), regex-strip those regions before minifying, minify the rest, then restore — do not try to configure it if the package doesn't support it.
  • Don't minify in tests and local dev by default. It makes view debugging and HTML diffs painful. Gate on app()->isProduction() or an explicit env flag.
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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment