voku/html-min
HtmlMin is a fast, easy-to-use PHP library that minifies HTML5 by stripping extra whitespace, comments, and unneeded characters without breaking structure. It also sorts attributes and CSS class names for better gzip compression, making pages smaller and faster to load.
Architecture fit
voku/html-min is a framework-agnostic PHP library (PSR-4, MIT, ext-dom only) that parses an HTML5 string into a DOMDocument subclass, strips comments/whitespace/redundant attributes, and re-serializes. It has no Laravel coupling and no service provider, so the architectural question is not whether it fits but where it belongs.
Three viable placements, in descending order of preference for a TPM:
TerminableMiddleware decorating text/html responses.The library's design is honest: it is a parse-and-reserialize minifier, not a regex trimmer. That is the right approach for correctness but means output is the DOM parser's normalization of your markup, not a whitespace-stripped copy of your original bytes. For a Laravel app whose HTML is assembled from Blade components, third-party packages, and JS-driven partials, that distinction is the core architectural risk.
Integration feasibility Low effort, high verification cost. A competent Laravel engineer produces a working middleware in under a day:
composer require voku/html-minApp\Http\Middleware\MinifyHtmlResponse — guard on status 200, Content-Type: text/html, exclude StreamedResponse/BinaryFileResponse/JsonResponse, call $response->setContent($minifier->minify($response->getContent())), wrap in try/catch with fail-open, and remove or recompute Content-Length (Symfony's setContent() does not update it).enabled, only_routes, except_routes, except_when_authenticated, log_failures.The real cost is the exclusion list. Any app with Livewire, Alpine.js, Filament, Mailables previews, <pre>/<textarea>-heavy content (docs, code samples, CMS output), email templates, or signed/verifiable HTML payloads needs per-route review. Budget 1–2 sprints of QA, not 1–2 days.
Technical risk
Key questions to answer before approval
<pre>, <textarea>, inline <script type="text/template">, or SVG/MathML foreign content? What does the library do to each in our sample corpus?ext-dom present in every target runtime — Laravel Vapor, Octane workers, container base images?composer why voku/html-min before adding a direct dependency.Stack fit
Good fit for a conventional Laravel 10/11 app: Composer-installed, no native extensions beyond ext-dom, no global state, compatible with Octane (stateless per-request usage — though the per-request DOM parse cost is amplified under Octane's model, since you are paying CPU on every request that could be served by a cache).
Migration path Treat this as an additive, reversible layer, not a migration:
Compatibility
Register in the web middleware group, appended last so it observes the final body after session, CSRF, and binding middleware. It must run before any response-caching layer stores the body (so the cache holds minified content) and its output must be what ETag/Content-Length are computed from. Do not place it upstream of compression middleware in a way that invalidates Vary or Content-MD5. Verify PHP 8.3/8.4 support against the changelog rather than the README's advertised floor.
Sequencing Do not ship this in the same release train as a framework upgrade, a caching-layer change, or a front-end hydration change. It is a low-value/high-debuggability-cost change; isolate it so any rendering regression has exactly one candidate cause. If the app is mid-migration to Livewire or Inertia, defer entirely.
Maintenance
Near-zero code maintenance (small, stable API: construct, minify()), but non-trivial configuration maintenance: every new route or Blade component that emits whitespace-sensitive or JS-hydrated markup becomes a potential exclusion. Assign an owner and add a PR checklist item — this is the most likely way the integration rots.
Support No commercial support, single maintainer, community issues only. Acceptable given MIT licensing and a ~1k-line codebase; fork-and-vendor is a realistic fallback. Budget a named engineer who can read the source if a serialization edge case surfaces.
Scaling CPU cost is linear in response size and paid per request. At high RPS this is measurable in aggregate even if small per request, and it is pure waste on responses that could be cached. The correct scaling pattern is to minify at cache-fill time, not at request time — minify once when a response enters a full-page cache, then serve the stored bytes. Absent a response cache, question whether the change scales at all.
Failure modes
try/catch returning the untouched response, plus an alert on the failure counter.<pre>/<textarea> or between inline elements, producing subtly wrong rendering that no error log catches. Mitigation: automated visual regression in CI against the route corpus.Content-Length if the header is not recomputed → truncated responses in some proxies.Ramp-up Engineer ramp-up: 2–4 hours to understand the API and write the middleware. Organizational ramp-up: 1–2 sprints for corpus capture, screenshot diffing, exclusion-list curation, and canary monitoring. The asymmetry is the headline — implementation is trivial, trusting the output is the investment, and the return is a single-digit compression improvement that the CDN layer could deliver with none of the risk. Recommend a decision gate after step 2 of the migration path, with "ship to edge instead" as the expected outcome for most apps and "approve for static/CMS routes only" as the favorable case.
How can I help you explore Laravel packages today?