justbetter/laravel-http3earlyhints
A Laravel package for HTTP/3 Early Hints that lets your app send 103 Early Hints responses, preloading critical assets and improving perceived page load performance with minimal configuration.
Install the package:
composer require justbetter/laravel-http3earlyhints
Publish the config:
php artisan vendor:publish --tag="http3-earlyhints-config"
The service provider and EarlyHints middleware are auto-discovered (Laravel 13 is supported as of 1.5.3). Look first at config/http3-earlyhints.php, the JustBetter\Http3EarlyHints\Facades\Http3EarlyHints facade, and the JustBetter\Http3EarlyHints\Http\Middleware\EarlyHints middleware.
First use case — preload your critical CSS from a service provider or middleware:
use JustBetter\Http3EarlyHints\Facades\Http3EarlyHints;
Http3EarlyHints::add('/build/assets/app.css', ['as' => 'style']);
The middleware flushes a 103 Early Hints response with Link: </build/assets/app.css>; rel=preload; as=style before Laravel sends the final response — the browser can start fetching assets while PHP renders.
AppServiceProvider::boot() so every response carries the same hints. Cache the list so it isn't rebuilt per request.public/build/manifest.json once (and cache it) and map entry names to emitted files, then register those as preloads. Prefer this to hardcoding paths — a manifest-sourced hint can't drift out of date.['rel' => 'preconnect'] for third-party origins (fonts, analytics, CDNs) and ['rel' => 'preload', 'as' => 'font', 'crossorigin' => 'anonymous'] for fonts. Mixing the rels in one collector is fine.serializable_classes config option lets the hint collection round-trip through serialization (workers, queues, jobs). Populate it with any custom hint classes you register.Http3EarlyHints facade or by inspecting the collector's toArray() rather than expecting a 103 status in $response->getStatusCode().curl -I --http2 https://your.app — you need to see a 103 block before the final 200. If you only see 200, your server or CDN is eating the hint.POST, PUT, DELETE). Browsers may re-issue prefetched GETs; guard the middleware or hint only on $request->isMethod('GET').crossorigin. Without as="font" and crossorigin="anonymous", the browser downloads the font twice — once for the hint, once for the CSS-referenced request.serializable_classes — otherwise the collector arrives empty.Http3EarlyHints::toArray() in Tinker or log it from a terminate() hook to confirm hints are populated; inspect Link headers in the network tab for the final response to confirm they're being emitted.$middleware->replace(...), or bind a custom collector in a service provider if you need different hint semantics.How can I help you explore Laravel packages today?