Skip to content

Commit 9c3041a

Browse files
committed
Update README.md
1 parent 4f7b1f8 commit 9c3041a

File tree

1 file changed

+91
-59
lines changed

1 file changed

+91
-59
lines changed

README.md

Lines changed: 91 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
# 🔥 Blaze
22

3+
Speed up your Laravel app by optimizing Blade component rendering performance.
4+
35
```
46
Rendering 25,000 anonymous components:
57
68
Without Blaze ████████████████████████████████████████ 500ms
79
With Blaze █ 13ms
810
```
911

10-
## Introduction
11-
12-
Blaze supercharges your Blade components by compiling them into direct PHP function calls, eliminating 91-97% of the rendering overhead. No configuration changes, no template modifications.
13-
1412
## Installation
1513

1614
You may install Blaze via Composer:
@@ -20,28 +18,20 @@ composer require livewire/blaze
2018
```
2119

2220
> [!TIP]
23-
> If you're using Flux, just install Blaze and you're good to go!
21+
> If you're using [Flux UI](https://fluxui.dev), just install Blaze and you're good to go - no configuration needed!
2422
25-
## Usage
26-
27-
Blaze is designed as a drop-in replacement for anonymous Blade components. It supports all essential features including props, slots, attributes, and `@aware`. The HTML output is identical to standard Blade rendering.
28-
29-
### Limitations
3023

31-
Blaze focuses on anonymous components. The following are not supported:
24+
## Introduction
3225

33-
- Class-based components
34-
- The `$component` variable
35-
- `View::share()` variables
36-
- View composers / creators
37-
- Component lifecycle events
26+
Out of the box, Blaze is a **drop-in replacement** for anonymous coponents. It does not require any changes to your existing component code and works by compiling components into optimized PHP code - this eliminates 91-97% of the rendering overhead.
3827

39-
> [!IMPORTANT]
40-
> When using `@aware`, both the parent and child components must use Blaze for values to propagate correctly.
28+
Blaze also offers two additional optimization strategies for even greater performance:
29+
- **Memoization** - a caching strategy for repeated components
30+
- **Folding** - pre-rendering components into static HTML
4131

42-
### Enabling Blaze
32+
## Getting started
4333

44-
Enable Blaze in your `AppServiceProvider`:
34+
Enable Blaze in your `AppServiceProvider` to optimize all component paths:
4535

4636
```php
4737
use Livewire\Blaze\Blaze;
@@ -52,14 +42,38 @@ public function boot(): void
5242
}
5343
```
5444

55-
This optimizes all [anonymous component paths](https://laravel.com/docs/12.x/blade#anonymous-component-paths).
56-
5745
After enabling Blaze, you should clear your compiled views:
5846

5947
```bash
6048
php artisan view:clear
6149
```
6250

51+
> [!CAUTION]
52+
> **If you're installing Blaze into an existing app**, enabling Blaze in all component paths can break your app. Consider scoping Blaze to specific directories or components until you've worked around the limitations described below.
53+
54+
### Limitations
55+
56+
Blaze supports all essential features of anonymous components and produces HTML output that is identical to Blade. That said, there are some limitations:
57+
58+
#### Accessing parent data using `@aware`
59+
60+
While `@aware` is supported, you must use Blaze in both parent and child for values to propagate correctly.
61+
62+
#### Accessing variables shared using `View::share()`
63+
64+
Variables shared via `View::share()` will NOT be injected automatically. You have to access them manually:
65+
66+
```blade
67+
{{ $__env->shared('key') }}
68+
```
69+
70+
#### Unsupported features
71+
72+
- **Class-based components** are not supported
73+
- **The `$component` variable** will not be accessible
74+
- **View composers / creators** will not run
75+
- **Component lifecycle events** will not fire
76+
6377
## Configuration
6478

6579
### Directory-Based Optimization
@@ -104,19 +118,21 @@ Component-level directives override directory-level settings.
104118

105119
## Optimization Strategies
106120

107-
Blaze offers three optimization strategies, each suited to different use cases:
121+
By default Blaze uses **Function Compilation**, which works for virtually all components and provides significant performance improvements — this is sufficient for most use cases. To go even further, you can consider the other strategies that require additional considerations.
108122

109123
| Strategy | Parameter | Best For | Overhead Reduction |
110124
|----------|-----------|----------|-------------------|
111125
| Function Compilation | (default) | General use | 91-97% |
112126
| Runtime Memoization | `memo` | Repeated identical components | 91-97% + deduplication |
113127
| Compile-Time Folding | `fold` | Maximum performance | 100% |
114128

115-
### Function Compilation
129+
Let's break down each strategy:
130+
131+
## Function Compilation
116132

117-
Function compilation is the default strategy. It transforms your components into optimized PHP functions, bypassing the entire component rendering pipeline while maintaining identical behavior to standard Blade.
133+
This strategy transforms your components into optimized PHP functions, bypassing the entire component rendering pipeline while maintaining identical behavior to standard Blade.
118134

119-
#### Benchmark Results
135+
### Benchmark Results
120136

121137
The following benchmarks represent 25,000 components rendered in a loop:
122138

@@ -132,7 +148,7 @@ The following benchmarks represent 25,000 components rendered in a loop:
132148

133149
These numbers reflect rendering pipeline overhead. If your components execute expensive operations internally, that work will still affect performance.
134150

135-
#### How It Works
151+
### How It Works
136152

137153
When you enable Blaze, components are compiled into direct function calls:
138154

@@ -168,7 +184,7 @@ Becomes:
168184
_c4f8e2a1(['type' => 'submit'], ['default' => 'Send']);
169185
```
170186

171-
### Runtime Memoization
187+
## Runtime Memoization
172188

173189
Runtime memoization caches component output during a single request. When a component renders with the same props multiple times, it only executes once.
174190

@@ -187,11 +203,14 @@ This strategy is ideal for components like icons and avatars that appear many ti
187203

188204
If `<x-icon name="check" />` appears 50 times on a page, it renders once and reuses the output.
189205

190-
### Compile-Time Folding
206+
## Compile-Time Folding
207+
208+
> [!CAUTION]
209+
> **Folding requires careful consideration**. Used incorrectly, it can cause subtle bugs that are difficult to diagnose. Make sure you fully understand the limitations described below before using this strategy.
191210
192211
Compile-time folding is Blaze's most aggressive optimization. It pre-renders components during compilation, embedding the HTML directly into your template. The component ceases to exist at runtime - there is no function call, no variable resolution, no overhead whatsoever.
193212

194-
#### Benchmark Results
213+
### Benchmark Results
195214

196215
Because folded components are rendered at compile-time, the runtime cost is effectively zero. The rendering time remains constant regardless of how many components you use:
197216

@@ -201,72 +220,85 @@ Because folded components are rendered at compile-time, the runtime cost is effe
201220
| 50,000 | 1,000ms | 0.68ms |
202221
| 100,000 | 2,000ms | 0.68ms |
203222

204-
The time doesn't grow because there are no components to render - just static HTML.
223+
### How It Works
205224

206-
> [!CAUTION]
207-
> Folding requires careful consideration. Used incorrectly, it can cause subtle bugs that are difficult to diagnose. Review the [Folding](#folding) section before enabling.
225+
This section covers the intricacies of compile-time folding. If you're using the default function compilation strategy, you can skip this section entirely.
208226

209-
#### How It Works
227+
#### Static props
228+
229+
Let's start with a simple component that only recieves a static prop like `color="red"`:
210230

211231
```blade
212232
@blaze(fold: true)
213233
214-
@props(['type' => 'button'])
234+
@props(['color'])
215235
216-
<button type="{{ $type }}" class="inline-flex">
236+
@php
237+
$classes = match($color) {
238+
'red' => 'bg-red-500 hover:bg-red-400',
239+
'blue' => 'bg-blue-500 hover:bg-blue-400',
240+
default => 'bg-gray-500 hover:bg-gray-400',
241+
};
242+
@endphp
243+
244+
<button class="{{ $classes }}" type="button">
217245
{{ $slot }}
218246
</button>
219247
```
220248

221249
When compiled:
222250

223251
```blade
224-
<x-button type="submit">Submit</x-button>
252+
<x-button color="red">Submit</x-button>
225253
```
226254

227255
Becomes:
228256

229257
```blade
230-
<button type="submit" class="inline-flex">
258+
<button class="bg-red-500 hover:bg-red-400" type="submit">
231259
Submit
232260
</button>
233261
```
234262

235-
## Folding
263+
This works flawlessly because all data needed to render the component is available at compile-time.
236264

237-
This section covers the intricacies of compile-time folding. If you're using the default function compilation strategy, you can skip this section entirely.
265+
#### Dynamic props
266+
267+
Because Blaze pre-renderes components during compilation, it doesn't have access to data that will be passed to the components at runtime. Blaze works around this by replacing dynamic values with placeholders during rendering and substituting the original expressions back into the final output.
268+
269+
To illustrate this, let's assign a random id to the button:
238270

239-
### How Folding Works
271+
```blade
272+
<x-button color="red" :id="Str::random()">Submit</x-button>
273+
```
240274

241-
When a component is folded, Blaze renders it at compile-time and embeds the output directly into your template. This eliminates virtually all runtime overhead but introduces constraints on what the component can do.
275+
During compilation, Blaze will analyze the component to identify dynamic values and store their values:
242276

243-
### Dynamic Attributes
277+
| Property | Dynamic value | Placeholder |
278+
|------|--------|--------|
279+
| `id` | `Str::random()` | ATTR_PLACEHOLDER_1 |
244280

245-
Blaze handles dynamic attributes that pass through `$attributes` unchanged using placeholder replacement:
281+
Next, it pre-renders the component using the placeholder:
246282

247283
```blade
248-
@blaze(fold: true)
249-
250-
<div {{ $attributes->class(['rounded-lg shadow-md p-6']) }}>
251-
{{ $slot }}
252-
</div>
284+
<x-button color="red" :id="ATTR_PLACEHOLDER_1">Submit</x-button>
253285
```
254286

255-
When called:
287+
Which compiles to:
256288

257289
```blade
258-
<x-card :class="$featured ? 'bg-yellow-50' : 'bg-white'">
259-
Content
260-
</x-card>
290+
<button class="bg-red-500 hover:bg-red-400" type="submit" id="ATTR_PLACEHOLDER_1">
291+
Submit
292+
</button>
261293
```
262294

263-
Blaze replaces the dynamic value with a placeholder, renders the component, then substitutes the original expression back:
295+
Before finalizing the output, Blaze substitutes the original dynamic expressions back into the HTML using the mapping table:
264296

265-
| Step | Result |
266-
|------|--------|
267-
| Placeholder | `<x-card class="__BLAZE_PH_1__">` |
268-
| Render | `<div class="rounded-lg shadow-md p-6 __BLAZE_PH_1__">` |
269-
| Replace | `<div class="... <?php echo e($featured ? '...' : '...'); ?>">` |
297+
```blade
298+
<button class="bg-red-500 hover:bg-red-400" type="submit" id="{{ Str::random() }}">
299+
Submit
300+
</button>
301+
```
270302

271303
### Props
272304

0 commit comments

Comments
 (0)