Blaze folds a component by rendering it at compile time, with dynamic attributes replaced by BLAZE_PLACEHOLDER_N_. When the folded component carries a wire:key, Livewire's precompiler has injected a runtime statement immediately before it:
SupportCompiledWireKeys::$currentLoop['key'] = <expr>;
Folding executes that statement, writing the placeholder into a public static.
Because compilation happens inside a request's render, the next <livewire:...> to mount inherits the poisoned value and receives a key like:
lw-2542294403-0-BLAZE_PLACEHOLDER_0_-1 # cold compile
lw-2542294403-0-1 # warm process
This is not cosmetic
On the next Livewire update the key no longer matches, SupportNestingComponents::hasPreviouslyRenderedChild() returns false, and the child component is fully re-mounted with a new id rather than being stubbed and reused.
Verified with a positive control through the real Livewire update endpoint:
- cold arm — key mismatch, child re-mounted with a new id, old id absent from the response
- warm arm — key matches, child stubbed and reused
Reproduction
php artisan view:clear
- Issue a request that renders a page containing a folded component with a
wire:key, followed by a nested <livewire:...> mount
- Compare the nested component's
wire:key against the same request in a warm process
Nothing is baked into any compiled file — it is process-global runtime state mutated during compilation.
Versions
livewire/blaze v1.0.15
livewire/livewire v4.4.0
livewire/flux v2.16.0
- PHP 8.4+
The trigger in our case is Flux's select/option/variants/default.blade.php:10, which carries wire:key="{{ $value }}" — but nothing here is specific to Flux. Any folded component carrying a wire:key should reproduce it.
Scope
Only cold compiles are affected, so artisan optimize hides it entirely in production. Local development and CI reach it.
We have not attempted a fix on our side: the only lever available to us is disabling the fold for that component, which costs several hundred extra Blade component instantiations per render to remove a symptom that never reaches production. A ComponentFolded listener does not work either — there is no pre-fold hook, so it can only reset rather than save/restore, and it would collide keys inside loops.
Which package is the right place to change this is your call — the interaction spans the precompiler's runtime statement and the fold that executes it.
Blaze folds a component by rendering it at compile time, with dynamic attributes replaced by
BLAZE_PLACEHOLDER_N_. When the folded component carries awire:key, Livewire's precompiler has injected a runtime statement immediately before it:Folding executes that statement, writing the placeholder into a public static.
Because compilation happens inside a request's render, the next
<livewire:...>to mount inherits the poisoned value and receives a key like:This is not cosmetic
On the next Livewire update the key no longer matches,
SupportNestingComponents::hasPreviouslyRenderedChild()returns false, and the child component is fully re-mounted with a new id rather than being stubbed and reused.Verified with a positive control through the real Livewire update endpoint:
Reproduction
php artisan view:clearwire:key, followed by a nested<livewire:...>mountwire:keyagainst the same request in a warm processNothing is baked into any compiled file — it is process-global runtime state mutated during compilation.
Versions
livewire/blazev1.0.15livewire/livewirev4.4.0livewire/fluxv2.16.0The trigger in our case is Flux's
select/option/variants/default.blade.php:10, which carrieswire:key="{{ $value }}"— but nothing here is specific to Flux. Any folded component carrying awire:keyshould reproduce it.Scope
Only cold compiles are affected, so
artisan optimizehides it entirely in production. Local development and CI reach it.We have not attempted a fix on our side: the only lever available to us is disabling the fold for that component, which costs several hundred extra Blade component instantiations per render to remove a symptom that never reaches production. A
ComponentFoldedlistener does not work either — there is no pre-fold hook, so it can only reset rather than save/restore, and it would collide keys inside loops.Which package is the right place to change this is your call — the interaction spans the precompiler's runtime statement and the fold that executes it.