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 Min Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

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:

  1. Edge/CDN layer (Fastly, Akamai, Cloudflare Workers). Zero application risk, zero PHP CPU cost. If the goal is purely payload reduction, this is the correct first move and makes the package unnecessary.
  2. Response middleware on cacheable, non-interactive pages only. Where this package actually earns its place — a thin TerminableMiddleware decorating text/html responses.
  3. Global middleware on all HTML. Strongly discouraged; see technical risk.

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-min
  • App\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).
  • Config file: enabled, only_routes, except_routes, except_when_authenticated, log_failures.
  • Feature flag (Pennant or config) so rollout is reversible without a deploy.

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

  • DOM re-serialization fidelity. Attribute ordering, self-closing tag style, and invalid-but-tolerated markup can shift. Low visual risk, non-zero risk for anything downstream that hashes or diffs HTML (visual regression suites, email snapshot tests, signed payloads).
  • JS-hydrated DOM. Livewire's morphdom diffs the server-rendered DOM against its own in-memory tree; removing inter-element whitespace text nodes between requests is a documented class of hydration mismatch. Treat interactive components as out of scope.
  • Marginal gain on top of gzip/Brotli. Expect a single-digit percentage improvement in compressed transfer size on typical Laravel pages. This is the central value question: the risk is real, the payoff is small, and it is frequently negative once per-request CPU is counted.
  • Bus factor. Single maintainer, low release cadence, small star count. The score of 2.43 reflects low notability rather than poor quality — the code is small, tested in CI, and easy to fork or vendor if abandoned. Mitigate with a pinned version and an in-repo fork contingency.

Key questions to answer before approval

  1. Is total byte reduction or TTFB the actual bottleneck, or is this cargo-cult optimization? What does the RUM/APM data say about HTML size versus other costs?
  2. Does the app render <pre>, <textarea>, inline <script type="text/template">, or SVG/MathML foreign content? What does the library do to each in our sample corpus?
  3. Are Livewire, Alpine, Inertia SSR, or Filament in use? If yes, scope minification to static marketing/CMS routes only.
  4. Does any downstream consumer hash, sign, or snapshot HTML (email rendering, PDF export, contract generation)?
  5. Is ext-dom present in every target runtime — Laravel Vapor, Octane workers, container base images?
  6. Is the package already present transitively (page-speed middleware packages commonly bundle a minifier of this type)? Check composer why voku/html-min before adding a direct dependency.
  7. What is the rollback story if a release breaks serialization — config flag, or redeploy?

Integration Approach

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:

  1. Baseline. Capture a corpus of 50–200 real production HTML responses across route archetypes (marketing, listing, detail, authenticated dashboard, error pages). Record gzipped size, uncompressed size, and rendering screenshots.
  2. Offline evaluation. Run the minifier against the corpus outside the request path. Measure byte savings after gzip, diff the DOM, and screenshot-compare. Decision gate: if compressed savings are under ~5%, stop — pursue edge minification or image/font optimization instead.
  3. Build the exclusion list from step 2 failures, encoded as config, not code.
  4. Stage rollout behind a flag with 100% of traffic and full error logging; minify failures must return the original body.
  5. Canary at 5% → 25% → 100%, gated on error rate, p95 latency, and visual regression CI.

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.

Operational Impact

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

  • Hard failure: uncaught exception or libxml error in middleware → 500s on every HTML page. Mitigation: fail-open try/catch returning the untouched response, plus an alert on the failure counter.
  • Silent corruption: over-aggressive whitespace collapse in <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.
  • Hydration divergence: Livewire/Alpine client mismatches, intermittent and hard to attribute. Mitigation: exclude interactive routes at the config level, not per-component.
  • Memory/time limit breaches on unusually large HTML documents. Mitigation: size cap with pass-through above the threshold.
  • Stale 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.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings