Laravel Magazine
Blade's @once, @pushOnce, and @prepend for Clean Asset Management

Blade's @once, @pushOnce, and @prepend for Clean Asset Management

Eric Van Johnson ·

A common Blade component pattern: a <x-rating-stars> component that needs a small Alpine.js snippet to handle hover states. Render that component once on a page and it works fine. Render it 12 times in a product grid, and if the script tag lives inside the component's view, it gets duplicated 12 times in the rendered HTML. @once exists specifically for this.

@once: render a block a single time no matter how many times it's reached

{{-- resources/views/components/rating-stars.blade.php --}}
<div x-data="ratingStars({{ $rating }})">
    {{-- star markup --}}
</div>

@once
    @push('scripts')
        <script>
            function ratingStars(initial) {
                return {
                    rating: initial,
                    hover: null,
                };
            }
        </script>
    @endpush
@endonce

The first time this component is rendered on a page, the @once block executes and the @push('scripts') content is queued. Every subsequent render of the same component on the same page skips the block entirely — Blade tracks which @once blocks have already fired per request. The function ratingStars() definition appears exactly once in the final HTML regardless of how many <x-rating-stars> tags are on the page.

@pushOnce: the shorthand for the common case

Since "push to a stack, but only once" is the most frequent use of @once, Blade offers a combined directive:

@pushOnce('scripts')
    <script>
        function ratingStars(initial) {
            return { rating: initial, hover: null };
        }
    </script>
@endPushOnce

This is identical to wrapping @push in @once — pick whichever reads more clearly in context. There's a matching @prependOnce for content that needs to go at the front of a stack instead of the end.

@prepend: ordering when it matters

Stacks are usually append-only, but sometimes ordering between pushed content matters — a base layout's core script needs to load before a component's script that depends on it. @prepend inserts content at the beginning of the stack instead of the end:

{{-- layouts/app.blade.php --}}
<head>
    @stack('scripts')
</head>
{{-- A component that must load before everything else pushed to 'scripts' --}}
@prepend('scripts')
    <script src="/js/chart-core.js"></script>
@endprepend

Combine @once and @prepend the same way as @pushOnce, by wrapping: @once @prepend(...) ... @endprepend @endonce.

Where this actually saves you

The payoff isn't just cleaner HTML output — duplicated <script> tags with function declarations will throw a "redeclaration" or silently redefine the function on every occurrence, and duplicated document.addEventListener() calls fire the same handler multiple times per event. For any Blade component that pairs markup with a script or style block, wrapping the asset half in @once (or @pushOnce) isn't an optimization — it's the difference between a component that's actually safe to render more than once per page and one that quietly breaks the second time it's used.

Stay Updated

Subscribe to our newsletter

Get latest news, tutorials, community articles and podcast episodes delivered to your inbox.

Weekly articles
We send a new issue of the newsletter every week on Friday.
No spam
We'll never share your email address and you can opt out at any time.