Skip to content

Commit 20cb545

Browse files
authored
Add boost skill (#132)
* Remove memo hits * Add boost skill * Rename commands
1 parent 799ebfb commit 20cb545

File tree

9 files changed

+726
-22
lines changed

9 files changed

+726
-22
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
name: blaze-optimize
3+
description: Set up and optimize Blade component rendering with Blaze. Use when installing Blaze, optimizing components, or configuring @blaze directives and strategies.
4+
license: MIT
5+
metadata:
6+
author: livewire
7+
---
8+
9+
# Blaze Optimize
10+
11+
Blaze compiles anonymous Blade components into optimized PHP functions, significantly reducing rendering overhead.
12+
13+
EXECUTE steps 1–5 IMMEDIATELY without asking the user. Do NOT prompt for confirmation or offer choices — these are safe, low-risk changes. Only pause at step 6 to present the summary.
14+
15+
---
16+
17+
## 1. Install
18+
19+
Check `composer.json` for `livewire/blaze`. If missing:
20+
21+
```bash
22+
composer require livewire/blaze:^1.0
23+
```
24+
25+
## 2. Codebase Scan
26+
27+
Quick scan before making changes. Do not read individual component files.
28+
29+
Check:
30+
- `composer.json` for `livewire/flux`, `livewire/flux-pro`, `livewire/livewire`, `livewire/blaze`
31+
- Component count: glob `resources/views/components/**/*.blade.php`
32+
- Directory structure under `resources/views/components/`
33+
- Custom component paths: grep providers for `anonymousComponentPath` or `anonymousComponentNamespace` — these register additional component directories that also need optimization
34+
- `app/Providers/AppServiceProvider.php` for existing `Blaze::optimize()` calls
35+
- `.env` for `BLAZE_ENABLED` or `BLAZE_DEBUG`
36+
37+
### Flux detected
38+
39+
Blaze optimizes Flux components automatically. No configuration needed — just install the package. If the project also has its own anonymous components, continue with setup for those.
40+
41+
### Already configured
42+
43+
Describe the current setup. Do not make further changes unless the user asks.
44+
45+
## 3. Compatibility Check
46+
47+
Before enabling Blaze for a directory, grep its components for patterns Blaze does not support. Exclude any components or directories that match:
48+
49+
| Pattern | What to grep for | Why |
50+
|---------|-----------------|-----|
51+
| Class-based components | PHP class files in `app/View/Components/` that correspond to component directories | Blaze only supports anonymous components |
52+
| `$component` variable | `$component` | Not available in Blaze |
53+
| View composers/creators | `View::composer(` or `View::creator(` in `app/Providers/` targeting component views | These do not fire for Blaze components |
54+
| `View::share()` variables | `View::share(` in providers, then grep components for those variable names | Shared variables are not auto-injected — must use `$__env->shared('key')` instead |
55+
| Rendered via `view()` | `view('components.` or `View::make('components.` | Blaze components can only be rendered using component tags (`<x-...>`) |
56+
57+
Report any incompatible components so they can be excluded in the next step.
58+
59+
## 4. Enable Compilation
60+
61+
Add to `AppServiceProvider::boot()`:
62+
63+
```php
64+
use Livewire\Blaze\Blaze;
65+
66+
public function boot(): void
67+
{
68+
Blaze::optimize()->in(resource_path('views/components'));
69+
}
70+
```
71+
72+
Include any custom component paths found in step 2:
73+
74+
```php
75+
Blaze::optimize()
76+
->in(resource_path('views/components'))
77+
->in(resource_path('views/other-components'));
78+
```
79+
80+
Exclude any directories or files flagged in the compatibility check:
81+
82+
```php
83+
Blaze::optimize()
84+
->in(resource_path('views/components'))
85+
->in(resource_path('views/components/legacy'), compile: false) // directory
86+
->in(resource_path('views/components/complex-widget.blade.php'), compile: false); // single file
87+
```
88+
89+
## 5. Enable Debug + Clear Views
90+
91+
Set `BLAZE_DEBUG=true` in `.env` so trace data is collected when the user browses pages. Then clear cached views:
92+
93+
```bash
94+
php artisan view:clear
95+
```
96+
97+
## 6. Summary Report
98+
99+
Keep the summary SHORT and concise. A few bullet points, no tables, no per-directory breakdowns. Only mention what changed and what was excluded. Example:
100+
101+
- Compilation enabled for `resources/views/components` (72 components)
102+
- No incompatible components found
103+
- `BLAZE_DEBUG=true` set in `.env`
104+
105+
If components were excluded, list them briefly. If there are refactors to suggest, add:
106+
107+
- **Suggested refactors:**
108+
- **Class-based components** — convert to anonymous so Blaze can compile them
109+
- **View::share / composer / creator reliance** — pass data via props instead, or use `$__env->shared('key')`
110+
111+
Then present the advanced optimization options. Use the SAME formatting as written below — numbered options with a clear ask for the user to pick one. Only include Option 3 if the compatibility check found refactors to suggest. If there are no refactors, omit Option 3 entirely. Mark Option 3 as RECOMMENDED when present, otherwise mark Option 1 as RECOMMENDED.
112+
113+
**When there are refactors to suggest:**
114+
115+
> **Want to go further?**
116+
>
117+
> **Option 1 — Trace-based optimization**
118+
> Browse your app with debug mode enabled (already active), make sure to visit the **slow or component-heavy pages**, then tell me you're done. I'll analyze the trace data and apply targeted memo/fold optimizations to the slowest components.
119+
>
120+
> **Option 2 — Code analysis**
121+
> Full codebase audit without trace data. **WARNING:** significantly more **token-intensive**, results are **speculative**, and incorrect optimizations can break components. Requires thorough testing.
122+
>
123+
> **Option 3 — Apply refactors first (RECOMMENDED)**
124+
> Apply the suggested refactors to bring excluded components into Blaze compilation. I'll come back to these options when done.
125+
>
126+
> Reply **1**, **2**, or **3** when ready (or skip if you don't need advanced optimization).
127+
128+
**When there are NO refactors:**
129+
130+
> **Want to go further?**
131+
>
132+
> **Option 1 — Trace-based optimization (RECOMMENDED)**
133+
> Browse your app with debug mode enabled (already active), make sure to visit the **slow or component-heavy pages**, then tell me you're done. I'll analyze the trace data and apply targeted memo/fold optimizations to the slowest components.
134+
>
135+
> **Option 2 — Code analysis**
136+
> Full codebase audit without trace data. **WARNING:** significantly more **token-intensive**, results are **speculative**, and incorrect optimizations can break components. Requires thorough testing.
137+
>
138+
> Reply **1** or **2** when ready (or skip if you don't need advanced optimization).
139+
140+
## STOP
141+
142+
You are done. Do NOT proceed with advanced optimization (memoization, folding) unless the user explicitly asks for it. When they do, read [references/advanced-optimization.md](references/advanced-optimization.md) for instructions.
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Advanced Optimization
2+
3+
These optimizations (memoization and folding) are more powerful but carry risk — they can affect component behavior if applied incorrectly and should be thoroughly tested.
4+
5+
## Option A: Trace-Based (preferred)
6+
7+
### 1. Collect trace data
8+
9+
Ask the user to visit pages in their browser, making sure to include the slow pages they want to optimize. `BLAZE_DEBUG=true` is already enabled from Phase 1, so trace data will be collected automatically.
10+
11+
Wait for the user to confirm they are done browsing before proceeding.
12+
13+
### 2. Analyze traces
14+
15+
Run:
16+
17+
```bash
18+
php artisan blaze:trace:list
19+
```
20+
21+
This shows pages the user visited with their load times. Identify the slowest pages, then drill into them:
22+
23+
```bash
24+
php artisan blaze:trace:show [id]
25+
```
26+
27+
This shows the slowest components for that page and how many were rendered.
28+
29+
### 3. Optimize slow components
30+
31+
Be THOROUGH and PROACTIVE. Analyze EVERY high-volume component from the trace data — do NOT dismiss components without reading them first. If a component is slow and has high render count, read it and determine what optimization applies. Apply optimizations immediately — do not ask the user for permission on each one.
32+
33+
For each slow component identified in the trace data:
34+
35+
1. Read the component file
36+
2. Evaluate it against BOTH memoization and folding — they are not mutually exclusive buckets. A component may fail one but qualify for the other.
37+
3. When applying folding, ALWAYS evaluate every prop, slot, and attribute for safe/unsafe. Never apply bare `@blaze(fold: true)` without checking.
38+
39+
**Memoization** — the MOST effective optimization for high-volume components. Use when:
40+
- Has no slots
41+
- Has no global state access
42+
- Is rendered many times with the same props (icons, avatars, badges)
43+
44+
IMPORTANT: If a high-volume component has a simple slot that only outputs text (e.g. `{{ $slot }}`), it is almost certainly better as a prop. Flag it for refactoring — converting the slot to a prop (like `label` or `text`) makes it memoizable, which is far more effective than folding at high render counts. See the "Suggest Refactors" section below.
45+
46+
Apply via service provider (preferred for entire directories like `icons/`):
47+
48+
```php
49+
Blaze::optimize()
50+
->in(resource_path('views/components'))
51+
->in(resource_path('views/components/icons'), memo: true);
52+
```
53+
54+
Or via directive (individual components):
55+
56+
```blade
57+
@blaze(memo: true)
58+
```
59+
60+
**Folding** — use when the component:
61+
- Has no global state access (or state is isolated with `@unblaze`)
62+
- Is rendered frequently, especially in loops
63+
64+
Components with slots CAN be folded — slots are pass-through by default. Only mark a slot `unsafe` if the component inspects it.
65+
66+
For each folding candidate:
67+
68+
1. Check for global state patterns — if ANY are found inside the component, do NOT fold. See [folding-safety.md](folding-safety.md) for the complete list.
69+
2. Classify EVERY `@props` value individually:
70+
- Pass-through (output directly in HTML, class strings, attributes) → mark `safe`
71+
- Used in logic (match, if/else, switch, ternary with multiple branches) → leave as default (auto-abort when dynamic)
72+
3. Check if slots are inspected (`$slot->hasActualContent()`, `$slot->isEmpty()`, `$slot->isNotEmpty()`) → mark as `unsafe`. If slots are just output (`{{ $slot }}`), they are pass-through and need no annotation.
73+
4. Check if `$attributes->get()` is used in logic → mark `attributes` as `unsafe`
74+
5. Add the directive with the CORRECT safe/unsafe parameters
75+
76+
```blade
77+
@blaze(fold: true)
78+
@blaze(fold: true, safe: ['level'])
79+
@blaze(fold: true, unsafe: ['slot'])
80+
@blaze(fold: true, unsafe: ['attributes'])
81+
```
82+
83+
For components that are mostly foldable but have a small section using global state, use `@unblaze`:
84+
85+
```blade
86+
@unblaze(scope: ['name' => $name])
87+
@error($scope['name'])
88+
<p class="text-red-500">{{ $message }}</p>
89+
@enderror
90+
@endunblaze
91+
```
92+
93+
Note: Variables from the component scope must be passed explicitly via the `scope` parameter.
94+
95+
## Option B: Code Analysis (fallback)
96+
97+
Warn the user that this approach is token-intensive and the optimizations are speculative compared to trace-based analysis.
98+
99+
Use a subagent to perform a full component audit. The subagent should use Glob and Grep extensively — do not read files line by line. For projects with 200+ components, use grep-based sampling.
100+
101+
The subagent should return a structured report covering:
102+
103+
1. **Component inventory** — For each component under `resources/views/components/`, grep for: `@props`, `{{ $slot }}` / named slots, slot inspection patterns (`$slot->hasActualContent()`, `$slot->isEmpty()`, `$slot->isNotEmpty()`), global state patterns (`auth()`, `@auth`, `@guest`, `Auth::`, `session(`, `Session::`, `request()`, `Request::`, `$errors`, `@error`, `now()`, `Carbon::`, `@csrf`, `csrf_`, `url()`, `route(`, `DB::`, `::where(`, `::find(`, `::first(`, `::get()`, `::all()`, `::count(`, `config(`, `cache(`)
104+
105+
2. **Usage analysis** — Grep all views for `<x-` tags. Count per component. List top 20 most-used.
106+
107+
3. **Loop detection** — Find `<x-` tags inside `@foreach`, `@for`, `@forelse`, `@while` blocks.
108+
109+
4. **Nesting analysis** — Which components use other `<x-` components internally.
110+
111+
Report format:
112+
113+
```
114+
COMPONENT AUDIT
115+
===============
116+
Total components: [N]
117+
118+
ALL COMPONENTS:
119+
- [path] — uses: [N], slots: [y/n], inspects-slots: [y/n], global-state: [y/n], loop: [y/n], props: [list]
120+
121+
MEMOIZATION CANDIDATES:
122+
- [name] — [count] uses, no slots, no global state
123+
124+
FOLDING CANDIDATES:
125+
- [name] — [count] uses, in [N] loops, slots: [y/n], inspects-slots: [y/n], props: [list], global-state: none
126+
127+
GLOBAL STATE (cannot fold):
128+
- [name] — uses: [patterns found]
129+
130+
NESTING CHAINS:
131+
- [parent] -> [child] -> [grandchild]
132+
```
133+
134+
Apply memoization and folding using the same rules as Option A.
135+
136+
## Suggest Refactors
137+
138+
After applying optimizations, identify components that are close to qualifying for a higher optimization level but are blocked by a small issue. Present these refactors to the user and APPLY them unless the user declines. Do not just list them and wait — tell the user what you're going to do and do it.
139+
140+
Only suggest refactors that are straightforward and have a clear payoff. Do not refactor components that are rarely used or where compile is already sufficient.
141+
142+
**Slots blocking memoization** — High-volume components rendered many times with the same props but using a simple slot that could be a prop instead. Refactor the component to accept a `label`/`text` prop, update ALL callers, then switch from fold/compile to memo:
143+
144+
```blade
145+
{{-- Before: has slot, cannot memoize --}}
146+
<x-badge color="green">Active</x-badge>
147+
148+
{{-- After: slot replaced with prop, can memoize --}}
149+
<x-badge color="green" label="Active" />
150+
```
151+
152+
When applying this refactor: grep for ALL callers, update every one, update the component, and change the strategy to `memo: true`.
153+
154+
**Global state blocking folding** — Components used in loops that would be good folding candidates, but contain a section that accesses global state. Extract the stateful part with `@unblaze`:
155+
156+
```blade
157+
{{-- Before: $errors blocks folding --}}
158+
<div>
159+
<label>{{ $label }}</label>
160+
<input name="{{ $name }}">
161+
@error($name) <p>{{ $message }}</p> @enderror
162+
</div>
163+
164+
{{-- After: stateful section extracted with @unblaze --}}
165+
@blaze(fold: true)
166+
<div>
167+
<label>{{ $label }}</label>
168+
<input name="{{ $name }}">
169+
@unblaze(scope: ['name' => $name])
170+
@error($scope['name']) <p>{{ $message }}</p> @enderror
171+
@endunblaze
172+
</div>
173+
```
174+
175+
## Verification
176+
177+
After applying any advanced optimizations:
178+
179+
1. Run `php artisan view:clear`
180+
2. Test the application — verify optimized components render correctly
181+
3. If using trace-based optimization, ask the user to revisit the same pages and re-run `php artisan blaze:trace:list` to compare render times
182+
4. If a component breaks, remove its `@blaze` directive or add `compile: false`
183+
184+
## Common Pitfalls
185+
186+
- Memoizing components that have slots — memoization requires slot-free components
187+
- Folding components that access global state (auth, session, request, errors, time, CSRF) — produces stale HTML
188+
- Folding components where props drive internal logic without marking them `safe`
189+
- Forgetting to run `php artisan view:clear` after changes

0 commit comments

Comments
 (0)