Weave Code
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

Web Link Laravel Package

symfony/web-link

Symfony WebLink component manages typed links between resources and serializes them to HTTP Link headers. Use it to advertise preload, prefetch, and other resource hints for faster navigation and HTTP/2 push, following HTML5 and W3C specs.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require symfony/web-link
    
  2. First use case: Preload critical assets (e.g., CSS/JS) in HTTP headers.
    use Symfony\Component\WebLink\GenericLinkProvider;
    use Symfony\Component\WebLink\HttpHeaderSerializer;
    use Symfony\Component\WebLink\Link;
    
    $linkProvider = new GenericLinkProvider();
    $linkProvider->addLink(new Link('preload', '/css/app.css', [
        'as' => 'style',
        'crossorigin' => true,
    ]));
    
    header('Link: ' . (new HttpHeaderSerializer())->serialize($linkProvider->getLinks()));
    

Where to Look First

  • Core classes:
    • Link (represents a single link with rel, href, and attributes).
    • GenericLinkProvider (aggregates links; immutable by design).
    • HttpHeaderSerializer (converts links to HTTP Link: header format).
  • Documentation: Symfony WebLink Docs (covers use cases like preloading, prefetching, and HTTP/2 push).

Implementation Patterns

Common Workflows

  1. Preloading Critical Assets Add preload links for above-the-fold resources (CSS, fonts, scripts):

    $provider = new GenericLinkProvider();
    $provider->addLink(new Link('preload', '/fonts/roboto.woff2', ['as' => 'font']));
    
  2. Prefetching Non-Critical Resources Use prefetch for future pages or lazy-loaded assets:

    $provider->addLink(new Link('prefetch', '/next-page'));
    
  3. HTTP/2 Push (Server-Side) Serialize links in the Link: header to enable HTTP/2 push:

    header('Link: ' . (new HttpHeaderSerializer())->serialize($provider->getLinks()));
    
  4. Dynamic Link Providers Extend GenericLinkProvider or implement LinkProviderInterface for context-aware links (e.g., route-based assets):

    class RouteAssetLinkProvider implements LinkProviderInterface {
        public function getLinks(): array {
            return [new Link('preload', route_to_asset('app.css'))];
        }
    }
    
  5. Parsing Incoming Links Parse Link: headers from HTTP responses (Symfony 8+):

    use Symfony\Component\WebLink\LinkHeaderParser;
    $links = (new LinkHeaderParser())->parse($response->getHeader('Link'));
    

Integration Tips

  • Symfony Framework: Use with Response objects:
    $response = new Response();
    $response->headers->addLink($provider->getLinks());
    
  • Twig Integration: Pass links to templates for <link> tags:
    {% for link in app.webLinkProvider.getLinks() %}
        <link rel="{{ link.rel }}" href="{{ link.href }}" {% for attr, value in link.attributes %} {{ attr }}="{{ value }}" {% endfor %}>
    {% endfor %}
    
  • Middleware: Inject links globally via middleware:
    public function handle(Request $request, Closure $next) {
        $response = $next($request);
        $response->headers->addLink($this->linkProvider->getLinks());
        return $response;
    }
    

Gotchas and Tips

Pitfalls

  1. Immutable Providers GenericLinkProvider is immutable. Use addLink() or withLink() to create new instances:

    // Wrong: $provider->addLink() returns void.
    // Correct: $provider = $provider->withLink(new Link(...));
    
  2. Header Serialization Quirks

    • Order matters: Links are serialized in the order they’re added.
    • Quoting: URLs with special characters (e.g., ?) must be quoted in headers:
      new Link('preload', '/search?q=test', ['as' => 'script']) // Serializes as: <'/search?q=test'>; rel="preload"; as="script"
      
  3. HTTP/2 Push Limitations

    • Only works if the server supports HTTP/2 push.
    • Browsers may ignore push hints if the resource is already cached.
  4. Rel/Attribute Validation

    • Custom rel values (e.g., modulepreload) must comply with W3C specs.
    • Invalid attributes (e.g., as="invalid") may be silently ignored.

Debugging

  • Validate Headers: Use browser dev tools (Network tab) to check if Link: headers are sent.
  • Log Links: Temporarily log serialized headers to verify content:
    error_log((new HttpHeaderSerializer())->serialize($provider->getLinks()));
    
  • Parse Errors: If parsing incoming headers fails, ensure the Link: header follows RFC 8288.

Extension Points

  1. Custom Link Providers Implement LinkProviderInterface for dynamic logic (e.g., route-based assets):

    class ApiDocumentationLinkProvider implements LinkProviderInterface {
        public function getLinks(): array {
            return [new Link('alternate', '/api-docs', ['type' => 'application/json'])];
        }
    }
    
  2. Attribute Normalization Override Link::getAttributes() to transform attributes before serialization:

    class CustomLink extends Link {
        public function getAttributes(): array {
            $attrs = parent::getAttributes();
            $attrs['priority'] = 'high'; // Force a default.
            return $attrs;
        }
    }
    
  3. Header Serializer Extensions Extend HttpHeaderSerializer to customize output (e.g., add a prefix):

    class CustomSerializer extends HttpHeaderSerializer {
        public function serialize(array $links): string {
            return 'Custom-Prefix: ' . parent::serialize($links);
        }
    }
    
  4. Link Header Parsing Use LinkHeaderParser to extract links from HTTP responses (e.g., for pagination):

    $links = (new LinkHeaderParser())->parse($response->getHeader('Link'));
    $nextPageLink = $links->get('next');
    

Performance Tips

  • Minimize Links: Only preload what’s critical for the current page.
  • Cache Providers: Reuse GenericLinkProvider instances across requests if links are static.
  • Avoid Duplicates: Use Link::sameAs() to check for existing links before adding:
    if (!$provider->hasLink($newLink)) {
        $provider = $provider->withLink($newLink);
    }
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport