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

Twig Deferred Extension Laravel Package

rybakit/twig-deferred-extension

Twig extension that lets you defer rendering of heavy blocks and run them later, improving perceived performance. Works with Twig templates to collect deferred parts and flush them when ready—handy for widgets, fragments, and complex layouts.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require rybakit/twig-deferred-extension
    

    Register the extension in your Laravel app’s Twig environment (typically in app/Providers/AppServiceProvider.php):

    use Rybakit\Twig\DeferredExtension;
    
    public function register()
    {
        $this->app->singleton(Twig_Environment::class, function ($app) {
            $loader = new \Twig\Loader\FilesystemLoader($app['config']['view.paths']);
            $twig = new \Twig\Environment($loader, [
                'cache' => storage_path('framework/views'),
            ]);
            $twig->addExtension(new DeferredExtension());
            return $twig;
        });
    }
    
  2. First Use Case Defer a block in a Twig template (e.g., resources/views/layouts/app.blade.php):

    {# Defer the 'scripts' block to render after the page loads #}
    {% block scripts %}
        {% deferred %}
            <script src="{{ asset('js/app.js') }}"></script>
        {% enddeferred %}
    {% endblock %}
    

    Render the template in a controller:

    return view('layouts.app');
    

Implementation Patterns

Workflow: Deferred Block Rendering

  1. Markup Deferral Use {% deferred %} to wrap content that should load asynchronously (e.g., scripts, heavy DOM elements):

    {% deferred %}
        <div id="heavy-widget">{{ include('widget.twig') }}</div>
    {% enddeferred %}
    
  2. Dynamic Deferral Conditionally defer blocks based on logic:

    {% if user.is_premium %}
        {% deferred %}
            {{ include('premium-content.twig') }}
        {% enddeferred %}
    {% endif %}
    
  3. Integration with Laravel Mix/Vite Combine with asset pipelines for optimized loading:

    {% deferred %}
        @vite(['resources/js/app.js'])
    {% enddeferred %}
    

Advanced Patterns

  • Nested Deferrals Defer blocks inside other deferred blocks (extension handles nesting automatically).
  • Partial Deferral Defer only specific parts of a block:
     {% block footer %}
         <div class="static-footer">...</div>
         {% deferred %}
             <div class="dynamic-footer">...</div>
         {% enddeferred %}
     {% endblock %}
    

Gotchas and Tips

Pitfalls

  1. Double Rendering Ensure deferred blocks aren’t rendered twice (e.g., in layouts and child templates). Use {% block %} to override parent blocks safely.

    {# Parent template #}
    {% block deferred_scripts %}{% endblock %}
    
    {# Child template #}
    {% block deferred_scripts %}
        {% deferred %}{{ parent() }}<script>...</script>{% enddeferred %}
    {% endblock %}
    
  2. Asset Paths in Deferred Blocks Use {{ asset() }} or {{ mix() }} inside deferred blocks to avoid 404s for static assets. The extension doesn’t modify asset paths.

  3. JavaScript Dependencies Deferred blocks execute in order. Avoid circular dependencies between deferred scripts.

Debugging

  • Missing Deferred Output Verify the extension is registered in the Twig environment. Check for errors in storage/logs/laravel.log.
  • Console Errors Wrap deferred scripts in try-catch blocks if they may fail:
    {% deferred %}
        <script>
            try { /* risky code */ } catch(e) { console.error(e); }
        </script>
    {% enddeferred %}
    

Extension Points

  1. Custom Deferral Logic Override the DeferredExtension class to modify how deferred blocks are rendered:

    class CustomDeferredExtension extends DeferredExtension {
        public function renderBlock(\Twig\Node\Node $node, \Twig\Environment $env, array $context) {
            // Custom logic here
            return parent::renderBlock($node, $env, $context);
        }
    }
    
  2. Global Configuration Set default attributes (e.g., async or defer for scripts) via the extension constructor:

    $extension = new DeferredExtension(['script_attributes' => 'async']);
    
  3. Testing Mock the extension in PHPUnit to test deferred behavior:

    $twig = new \Twig\Environment($loader);
    $twig->addExtension(new DeferredExtension());
    $this->assertStringContainsString('deferred="true"', $twig->render('template.twig'));
    
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.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium