Blade's @once, @pushOnce, and @prepend for Clean Asset Management
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.