Speed up your Laravel app by optimizing Blade component rendering performance.
β οΈ Early stages - This is an early-stage perimental package. APIs may change, and edge cases have yet to be worked out. Please test thoroughly and report any issues!
Rendering 25,000 pure button components:
Without Blaze ββββββββββββββββββββββββββββββββββββββββ 750ms
With Blaze ββ 45ms
~17x faster
Blaze is a Laravel package that dramatically improves the rendering performance of your Blade components through compile-time optimization. It identifies static portions of your templates and pre-renders them, removing much of Blade's runtime overhead.
You can install the package via composer:
composer require livewire/blaze
To optimize a Blade component for performance, simply add the @pure
directive at the top of your component file.
The @pure
directive signals that your component is "pure" - meaning it has no side effects and always renders the same output for the same input (no auth checks, no database queries, no time-dependent content). Think of these as your basic UI building blocks like buttons, cards, and badges.
Using Flux? All eligible Flux components are already marked with
@pure
- you don't need to do anything! Just install Blaze and enjoy the performance boost.
{{-- resources/views/components/button.blade.php --}}
@pure
@props(['variant' => 'primary'])
<button type="button" class="btn btn-{{ $variant }}">
{{ $slot }}
</button>
When you use this component in your templates:
<x-button variant="secondary">
Save
</x-button>
Blaze will automatically optimize it during compilation, pre-rendering the static parts while preserving dynamic content.
The @pure
directive tells Blaze that a component has no runtime dependencies and can be safely optimized. Only add it to components that render the same way every time they're compiled.
Ask yourself these questions about your component:
- Does it work the same for all users? (no auth checks, no user-specific content)
- Does it work the same on every request? (no request data, no CSRF tokens)
- Does it work the same at any time? (no timestamps, no "time ago" formatting)
- Does it only use the props you pass in? (no session data, no database queries)
- Are all child components it renders also pure? (no dynamic components hardcoded inside)
If you answered YES to all questions β Add @pure
If you answered NO to any question β Don't add @pure
Think of @pure
components as "design system" components - they're the building blocks that:
- Look the same for everyone
- Only change based on props you explicitly pass
- Could be shown in a component library without any application context
Examples: buttons, cards, badges, icons, layout grids, typography components
Not pure : anything that's "smart" or "connected" - forms (CSRF), navigation (active states), user avatars (auth), timestamps (time), paginated tables (request state).
For developers familiar with functional programming: Think of @pure
components like pure functions - they always produce the same output for the same input, with no side effects or dependencies on external state.
These components are good candidates for optimization:
{{-- Static UI components --}}
@pure
<div class="card p-4 rounded shadow">
{{ $slot }}
</div>
{{-- Components that only depend on passed props --}}
@pure
@props(['size' => 'md', 'color' => 'blue'])
<button class="btn btn-{{ $size }} text-{{ $color }}">
{{ $slot }}
</button>
Avoid @pure
for components that have runtime dependencies:
{{-- CSRF tokens change per request --}}
<form method="POST">
@csrf <!-- β Don't use @pure -->
<button type="submit">Submit</button>
</form>
{{-- Authentication state changes at runtime --}}
@auth <!-- β Don't use @pure -->
<p>Welcome back!</p>
@endauth
{{-- Request data varies per request --}}
@props(['href'])
<a href="{{ $href }}" @class(['active' => request()->is($href)])> <!-- β Don't use @pure -->
{{ $slot }}
</a>
{{-- Error bags are request-specific --}}
@if($errors->has('email')) <!-- β Don't use @pure -->
<span class="error">{{ $errors->first('email') }}</span>
@endif
{{-- Session data changes at runtime --}}
<div>Welcome, {{ session('username') }}</div> <!-- β Don't use @pure -->
{{-- Components using @aware --}}
@aware(['theme']) <!-- β Don't use @pure -->
@props(['theme' => 'light'])
<div class="theme-{{ $theme }}">{{ $slot }}</div>
{{-- Pagination components --}}
@props(['paginator']) <!-- β Don't use @pure -->
<div class="pagination">
{{ $paginator->links() }}
</div>
{{-- Components containing non-pure children --}}
@pure <!-- β WRONG: This table contains pagination which is dynamic -->
@props(['items'])
<table class="table">
@foreach($items as $item)
<tr><td>{{ $item->name }}</td></tr>
@endforeach
<x-table-pagination :paginator="$items" />
</table>
Be careful with these patterns that might seem safe but can cause issues:
{{-- Time-dependent content --}}
<p>Generated on {{ now() }}</p> <!-- Changes every request -->
{{-- User-specific content --}}
<p>Hello {{ auth()->user()->name }}</p> <!-- Different per user -->
{{-- Environment-dependent values --}}
<script src="{{ config('app.cdn_url') }}/app.js"></script> <!-- Might change -->
{{-- Components that CONTAIN other non-pure components --}}
@pure <!-- β May break if child components are dynamic -->
<div class="wrapper">
<x-user-greeting /> <!-- If this uses auth(), the parent can't be @pure -->
</div>
Even with @pure
, Blaze only folds components when it can safely pre-render them at compile-time:
{{-- β
CAN be folded - static date value --}}
<x-date-formatter date="2024-01-15" />
{{-- β CANNOT be folded - dynamic date variable --}}
<x-date-formatter :date="$user->created_at" />
Why? Blaze needs actual values at compile-time to pre-render. When you pass dynamic variables (like $user->created_at
), Blaze doesn't know their values during compilation, so it skips folding and renders normally at runtime. This happens automatically - your component still works, it just won't be optimized.
Note: If your @pure
component isn't being folded, check if you're passing dynamic variables to it. The component itself is fine - it's the dynamic data preventing optimization.
- Start with simple components: Begin with basic UI components like buttons, cards, and badges
- Check your dependencies: If your component uses any Laravel helpers or global variables, think twice
- Test thoroughly: After adding
@pure
, verify the component still works correctly across different requests - Blaze is forgiving: If a component can't be optimized, Blaze will automatically fall back to normal rendering
While our benchmark shows up to 17x improvement for rendering thousands of components, real-world gains are more nuanced:
Most pages: 10-30ms faster rendering
- Reasonably sized pages with a few hundred components will see modest but meaningful improvements
Heavy component pages: 50-100ms+ faster
- Data tables with dozens/hundreds of rows
- Select dropdowns with many options
- Dashboard grids with repeated cards
- Any page with significant component repetition
Blaze is designed to fail gracefully - when it encounters an error during component folding, it automatically falls back to normal Blade rendering. This ensures your application never breaks due to optimization attempts.
However, when debugging why a component isn't being optimized, you might want to see the actual error that's causing Blaze to skip folding:
// In a service provider or debug environment...
app('blaze')->debug();
When debug mode is enabled:
- Blaze will not fall back gracefully
- Instead, it will throw the actual exception that occurred during folding
- This helps you identify issues like:
- Invalid prop types (e.g., passing a string to a date formatter expecting a Carbon instance)
- Missing required props
This repository includes an AGENTS.md
file specifically designed for AI assistants (like GitHub Copilot, Cursor, or Claude). If you're using an AI tool to help with your Laravel project:
- Point your AI assistant to the AGENTS.md file when asking about Blaze optimization
- The file contains detailed guidance for analyzing components and determining
@pure
eligibility - Use it for automated analysis - AI assistants can help audit your entire component library
Example prompts for AI assistants:
- "Using the AGENTS.md file, analyze my components and tell me which can use @pure"
- "Help me add @pure to all eligible components following the AGENTS.md guidelines"
- "Check if this component is safe for @pure based on AGENTS.md"
The MIT License (MIT). Please see License File for more information.