If you attended Laracon or are big into Livewire then you might have heard about Blaze. It's a new "high-performance Blade compiler" from the Livewire team that makes your Blade rendering Blazingly Fast™. Even a simple <x-component /> tag carries more runtime baggage than you'd expect, and Blaze strips most of it away by resolving what it can at compile time and optimizing how Laravel renders Blade components.
Let's explore how Blaze works by building two progressively capable toy implementations from scratch. We'll start simple and layer on complexity until we have something that mirrors the real thing. This will give you a solid mental model of what's happening every time Blaze touches one of your templates.
Install Blaze into your Laravel project by running:
composer require livewire/blaze
If you have a Livewire application using Flux, that's it! Blaze will automatically kick in and optimize your Flux components. Here's a before and after comparison on an application using Livewire, Flux and Blaze:

WOW that's fast! Let's take a look at the clever ways by which Blaze accomplishes this.
First, let's clarify: Blaze isn't locked into Livewire or Flux—you can use it in any Laravel project. You can opt in individual components by adding the @blaze directive at the top of a Blade file, or you can point Blaze at an entire directory from a service provider:
use Livewire\Blaze\Blaze;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Blaze::optimize()->in(resource_path('views/components'));
// ...
}
Blaze delivers its performance wins by shifting work from runtime to compile time. It offers three optimization strategies:
The Function Compiler is the newest addition to Blaze; however, folding is what started it all. It borrows a classic compiler design technique called constant folding (one which I'm sure we are all very familiar with right!?).
To understand how these optimizations work under the hood, we'll build two basic clones from scratch: Smol Blaze will highlight compile time folding. Then we will take it up a notch and put together Lil Blaze which adds the full pipeline—including the Function Compiler (Blaze's default strategy)—to show how Blaze is structured.
Now, we just threw a bunch of big abstract words around, so let's explain what constant folding actually does, in simple terms.
In compiler optimization land (aka the thing we are likely all super familiar with, right!?), constant folding reduces expressions like 3 + 5 to 8 during compilation, saving the CPU from calculating it at runtime.
Say that for readability you declare the MAX_UPLOAD_SIZE like so:
// Source
const MAX_UPLOAD_SIZE = 10 * 1024 * 1024; // 10MB in bytes
At compile time, the compiler evaluates the expression and replaces it with the result, treating it as a constant.
// After constant folding
const MAX_UPLOAD_SIZE = 10485760;
Now this is a trivial example (and mildly deceiving given that Node also handles part of this optimization at runtime). However, hopefully you see how unresolved expressions could quickly add up across a large codebase. Resolving these constants at compile time rapidly speeds things up.
Let's say you have <x-alert type="error" /> defined as:
@props(['type' => 'info'])
<div class="{{ $type }}">{{ $slot }}</div>
Then we use it like this:
<x-alert type="error">
I'm sorry dave, I'm afraid I can't do that.
</x-alert>
PHP, our beloved runtime language and savior, can't parse Blade out of the box, thus the Blade compiler needs to compile the Blade Component (excuse the reiteration) into something PHP can execute. Here's what our <x-alert type="error" ... looks like once compiled:
<?php $attributes ??= new \Illuminate\View\ComponentAttributeBag;
$__newAttributes = [];
$__propNames = \Illuminate\View\ComponentAttributeBag::extractPropNames((['type' => 'info']));
foreach ($attributes->all() as $__key => $__value) {
if (in_array($__key, $__propNames)) {
$$__key = $$__key ?? $__value;
} else {
$__newAttributes[$__key] = $__value;
}
}
$attributes = new \Illuminate\View\ComponentAttributeBag($__newAttributes);
unset($__propNames);
unset($__newAttributes);
foreach (array_filter((['type' => 'info']), 'is_string', ARRAY_FILTER_USE_KEY) as $__key => $__value) {
$$__key = $$__key ?? $__value;
}
$__defined_vars = get_defined_vars();
foreach ($attributes->all() as $__key => $__value) {
if (array_key_exists($__key, $__defined_vars)) unset($$__key);
}
unset($__defined_vars, $__key, $__value); ?>
<div class="<?php echo e($type); ?>"><?php echo e($slot); ?></div><?php /**PATH /resources/views/components/alert.blade.php ENDPATH**/ ?>
Now, any time we make use of the <x-alert /> component, the Blade view that uses it is transformed like this:
<?php if (isset($component)) { $__componentOriginal5194778a3a7b899dcee5619d0610f5cf = $component; } ?>
<?php if (isset($attributes)) { $__attributesOriginal5194778a3a7b899dcee5619d0610f5cf = $attributes; } ?>
<?php $component = Illuminate\View\AnonymousComponent::resolve(['view' => 'components.alert','data' => ['type' => 'error']] + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? $attributes->all() : [])); ?>
<?php $component->withName('alert'); ?>
<?php if ($component->shouldRender()): ?>
<?php $__env->startComponent($component->resolveView(), $component->data()); ?>
<?php if (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php $attributes = $attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
<?php $component->withAttributes(['type' => 'error']); ?>
I'm sorry dave, I'm afraid I can't do that.
<?php echo $__env->renderComponent(); ?>
<?php endif; ?>
<?php if (isset($__attributesOriginal5194778a3a7b899dcee5619d0610f5cf)): ?>
<?php $attributes = $__attributesOriginal5194778a3a7b899dcee5619d0610f5cf; ?>
<?php unset($__attributesOriginal5194778a3a7b899dcee5619d0610f5cf); ?>
<?php endif; ?>
<?php if (isset($__componentOriginal5194778a3a7b899dcee5619d0610f5cf)): ?>
<?php $component = $__componentOriginal5194778a3a7b899dcee5619d0610f5cf; ?>
<?php unset($__componentOriginal5194778a3a7b899dcee5619d0610f5cf); ?>
<?php endif; ?><?php /**PATH /resources/views/index.blade.php ENDPATH**/ ?>
These are small examples, however I hope you can see how this overhead could add real bloat to a large codebase with lots of components—and even more so with component libraries.
We'll implement "Smol Blaze" to read a component's source at compile time and inline the resulting HTML directly into the template. This demo is deliberately minimal and only tackles folding, but it will help illustrate the moving pieces at play. We will keep all parts in the AppServiceProvider and similar to Blaze also use regular expressions (although we'll take time to demystify the magic).
We will use Blade::prepareStringsForCompilationUsing to intercept the raw template string before Blade compiles it.
// App/Providers/AppServiceProvider.php
public function register(): void
{
Blade::prepareStringsForCompilationUsing(function (string $template) {
return $this->foldComponents($template);
});
}
Let's scan the templates for self closing component tags (like <x-icon name="user" />) using a dash of regex. Check out the regex pattern:
protected function foldComponents(string $template): string
{
return preg_replace_callback(
'/<x-(\w+)\s+([^>]+?)\/>/i',
fn ($matches) => $this->foldComponent($matches[1], $matches[2]),
$template
);
}
Now for each match, let's locate the corresponding Blade file. If it doesn't exist, we'll opt out and return the original tag.
protected function foldComponent(string $name, string $attributes): string
{
$path = resource_path("views/components/{$name}.blade.php");
if (! file_exists($path)) {
return "<x-{$name} {$attributes} />";
}
$source = file_get_contents($path);
$source = preg_replace('/@\w+[^\n]*\n?/', '', $source);
return $this->replaceAttributes($source, $attributes);
}
Last, we need to parse the attributes string and replace the corresponding variables in the component source.
protected function replaceAttributes(string $html, string $attributes): string
{
preg_match_all('/(\w+)="([^"]*)"/', $attributes, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$key = $match[1];
$value = $match[2];
$html = str_replace('{{ $' . $key . ' }}', $value, $html);
}
return $html;
}
Your final AppServiceProvider should look like so
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
Blade::prepareStringsForCompilationUsing(function (string $template) {
return $this->foldComponents($template);
});
}
public function boot(): void {}
private function foldComponents(string $template): string
{
return preg_replace_callback(
'/<x-(\w+)\s+([^>]+?)\/>/i',
fn ($matches) => $this->foldComponent($matches[1], $matches[2]),
$template
);
}
private function foldComponent(string $name, string $attributes): string
{
$path = resource_path("views/components/{$name}.blade.php");
if (! file_exists($path)) {
return "<x-{$name} {$attributes} />";
}
$source = file_get_contents($path);
$source = preg_replace('/@\w+[^\n]*\n?/', '', $source);
return $this->replaceAttributes($source, $attributes);
}
private function replaceAttributes(string $html, string $attributes): string
{
preg_match_all('/(\w+)="([^"]*)"/', $attributes, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$key = $match[1];
$value = $match[2];
$html = str_replace('{{ $'.$key.' }}', $value, $html);
}
return $html;
}
}
Smol Blaze only handles self-closing tags with static attributes, and can't deal with opening/closing tag pairs, dynamic attributes, slots, or nested components. Let's fix that! Lil Blaze's transformation journey also starts at Blade::prepareStringsForCompilationUsing, but the template passes through a pipeline of discrete stages:

Let's start by scaffolding the pipeline. The LilBlaze.php class will the entry point, and each step will be a call to a private method on the class:
// app/LilBlaze/LilBlaze.php
<?php
namespace App\LilBlaze;
class LilBlaze
{
private array $folded = [];
public function compile(string $template): string
{
// Protect @php/@verbatim blocks
[$template, $blocks] = $this->store($template);
// Split into tokens
$tokens = $this->tokenize($template);
// Build AST from tokens
$nodes = $this->parse($tokens);
// Apply optimization
$this->walk($nodes);
// Render AST back to string
$output = implode('', array_map(fn ($n) => $n->render(), $nodes));
// Stamp folded dependencies
$output = $this->stamp($output);
// Restore protected blocks
return $this->restore($output, $blocks);
}
}
Before we tokenize, we need to protect blocks that might contain explicit code.
// app/LilBlaze/LilBlaze.php
private function store(string $template): array
{
$blocks = [];
$counter = 0;
$replace = function ($m) use (&$blocks, &$counter) {
$placeholder = "__LILBLAZE_BLOCK_{$counter}__";
$blocks[$placeholder] = $m[0];
$counter++;
return $placeholder;
};
$template = preg_replace_callback('/@verbatim(.*?)@endverbatim/s', $replace, $template);
// Same pattern for @php ... @endphp blocks
$template = preg_replace_callback('/@php(.*?)@endphp/s', $replace, $template);
return [$template, $blocks];
}
At the end of the pipeline, restore() puts the original blocks back:
private function restore(string $template, array $blocks): string
{
foreach ($blocks as $placeholder => $original) {
$template = str_replace($placeholder, $original, $template);
}
return $template;
}
Blaze does a similar(ish) thing, but through reflection calls Laravel's private BladeCompiler::storeUncompiledBlocks() method before tokenization.
Here are the three small classes our pipeline will use. A Token is what the tokenizer produces, a typed chunk of the template:
// app/LilBlaze/Token.php
class Token
{
public function __construct(
// 'text', 'tag_open', 'tag_close', 'tag_self_close'
public readonly string $type,
// raw matched string
public readonly string $content,
// component name
public readonly string $name = '',
// attribute string (the 'type="error" class="bold"' in <x-alert type="error" class="bold">)
public readonly string $attributes = '',
) {}
}
The parser converts tokens into an AST made of two node types. TextNode is a leaf, plain text or already processed HTML:
// app/LilBlaze/TextNode.php
class TextNode
{
public function __construct(
public readonly string $content,
) {}
public function render(): string
{
return $this->content;
}
}
ComponentNode can have children (text, nested components, slots) and knows how to render itself back into a Blade tag if no strategy handles it:
// app/LilBlaze/ComponentNode.php
class ComponentNode
{
public array $children;
public function __construct(
public readonly string $name,
public readonly string $attributes = '',
array $children = [],
public readonly bool $selfClosing = false,
) {
$this->children = $children;
}
public function render(): string
{
$attrs = $this->attributes ? " {$this->attributes}" : '';
if ($this->selfClosing) {
return "<x-{$this->name}{$attrs} />";
}
$children = implode('', array_map(fn ($n) => $n->render(), $this->children));
return "<x-{$this->name}{$attrs}>{$children}</x-{$this->name}>";
}
}
Smol Blaze used a single preg_replace_callback to find self closing tags. Lil Blaze splits the template into a flat array of typed Token objects, opening, closing, self closing, and text:
// app/LilBlaze/LilBlaze.php
private function tokenize(string $template): array
{
preg_match_all(
'/<\/?x-[\w\-:.]+[^>]*?\/?>/i',
$template,
$rawMatches,
PREG_OFFSET_CAPTURE
);
$result = collect($rawMatches[0])
->reduce(function ($carry, $match) use ($template) {
[$raw, $pos] = $match;
if ($pos > $carry['offset']) {
$carry['tokens'][] = new Token('text', substr($template, $carry['offset'], $pos - $carry['offset']));
}
$carry['tokens'][] = $this->classifyToken($raw);
$carry['offset'] = $pos + strlen($raw);
return $carry;
}, ['tokens' => [], 'offset' => 0]);
if ($result['offset'] < strlen($template)) {
$result['tokens'][] = new Token('text', substr($template, $result['offset']));
}
return $result['tokens'];
}
The classifyToken() method determines if a raw tag string is opening, closing, or self closing:
// app/LilBlaze/LilBlaze.php
private function classifyToken(string $raw): Token
{
if (str_starts_with($raw, '</')) {
preg_match('/<\/x-([\w\-:.]+)\s*>/', $raw, $matches);
return new Token('tag_close', $raw, $matches[1] ?? '');
}
if (str_ends_with(rtrim($raw, " \t>"), '/')) {
preg_match('/<x-([\w\-:.]+)\s*(.*?)\s*\/>/s', $raw, $matches);
return new Token('tag_self_close', $raw, $matches[1] ?? '', trim($matches[2] ?? ''));
}
preg_match('/<x-([\w\-:.]+)((?:\s[^>]*)?)>/s', $raw, $matches);
return new Token('tag_open', $raw, $matches[1] ?? '', trim($matches[2] ?? ''));
}
> inside attribute values (:class="$a > $b ? 'bg-red' : 'bg-blue'"), whereas our pure regex approach will fumble.Now we need to convert the tokens into a nested AST.
// app/LilBlaze/LilBlaze.php
private function parse(array $tokens): array
{
$stack = [];
return collect($tokens)
->reduce(function ($root, Token $token) use (&$stack) {
if ($token->type === 'tag_open') {
$node = new ComponentNode($token->name, $token->attributes);
$this->addChild($root, $stack, $node);
$stack[] = $node;
return $root;
}
match ($token->type) {
'text' => $this->addChild($root, $stack, new TextNode($token->content)),
'tag_self_close' => $this->addChild($root, $stack, new ComponentNode(
$token->name, $token->attributes, [], true,
)),
'tag_close' => array_pop($stack),
default => null,
};
return $root;
}, []);
}
private function addChild(array &$root, array &$stack, TextNode|ComponentNode $node): void
{
if (empty($stack)) {
$root[] = $node;
} else {
$stack[count($stack) - 1]->children[] = $node;
}
}
addChild places the node either at the root level or as a child of whatever ComponentNode is currently on top of the stack.
For example, this template:
<x-alert type="error">
I'm sorry dave, I'm afraid I can't do that.
</x-alert>
Produces this tree:
[
new ComponentNode(
name: 'alert',
attributes: 'type="error"',
children: [
new TextNode("\n I'm sorry dave, I'm afraid I can't do that.\n"),
],
),
]
For each ComponentNode, two strategies are tried in order. The Function Compiler (compileNode) is the primary strategy and handles virtually all components. Folding is only attempted when explicitly enabled and only succeeds when all attributes are static. If folding returns null (can't fold), the Function Compiler takes over:
// app/LilBlaze/LilBlaze.php
private function walk(array &$nodes): void
{
foreach ($nodes as $i => $node) {
if (! ($node instanceof ComponentNode)) {
continue;
}
if (! $node->selfClosing) {
$this->walk($node->children);
}
$result = $this->fold($node) ?? $this->compileNode($node);
if ($result !== null) {
$nodes[$i] = $result;
}
}
}
When a strategy succeeds, it converts the ComponentNode into a TextNode. If it returns null, the next strategy gets a shot.
@blaze(fold: true) or per directory via Blaze::optimize(). When folding is enabled but can't proceed (e.g. when dynamic props are detected), it falls back to function compilation. Memoization sits alongside these as a runtime caching layer for components that appear repeatedly with the same props. We skip memoize in Lil Blaze since fold and compile are purely compile time transformations.Smol Blaze demonstrated this optimization, but now it's gated behind a safety check: if any attribute is dynamic (:class="$expr"), folding is skipped.
// app/LilBlaze/LilBlaze.php
private function fold(ComponentNode $node): ?TextNode
{
$path = resource_path("views/components/{$node->name}.blade.php");
if (! file_exists($path)) {
return null;
}
if (preg_match('/:\w+\s*=/', $node->attributes)) {
return null;
}
preg_match_all('/(\w+)="([^"]*)"/', $node->attributes, $matches, PREG_SET_ORDER);
$source = file_get_contents($path);
$source = preg_replace('/@\w+[^\n]*\n?/', '', $source);
// Replace attributes
foreach ($matches as $match) {
$source = str_replace('{{ $'.$match[1].' }}', $match[2], $source);
}
// Replace default slot from children
if (! $node->selfClosing) {
$slotContent = implode('', array_map(fn ($n) => $n->render(), $node->children));
$source = str_replace('{{ $slot }}', $slotContent, $source);
}
$source = preg_replace('/\{\{\s*\$\w+\s*\}\}/', '', $source);
$this->recordFolded($node->name, $path);
return new TextNode($source);
}
Folder replaces dynamic attributes with BLAZE_PLACEHOLDER_* strings, does an isolated Blade render at compile time, then restores the placeholders with the original expressions. It also checks for "problematic patterns" like stateful references ($errors, @csrf, session()) that can't be evaluated at compile time.In scenarios where we can't fold, we'll swap out Laravel's heavy function calls (the ComponentAttributeBag, extractPropNames, get_defined_vars dance we saw earlier) with a simple require_once + function call. Before we look at the code, here's the end result we're aiming for. Given this template:
<x-alert :type="$type">
I'm sorry dave, I'm afraid I can't do that.
</x-alert>
The compile strategy produces a standalone PHP function for the component:
<?php if (!function_exists('_lilblaze_a1b2c3d4e5f6')):
function _lilblaze_a1b2c3d4e5f6(array $__data = []) {
$__data = array_merge(['type' => 'info'], $__data);
extract($__data);
ob_start();
?>
<div class="<?php echo e($type); ?>"><?php echo e($slot); ?></div>
<?php
echo ltrim(ob_get_clean());
}
endif; ?>
And the call site in the compiled view becomes:
<?php ob_start(); ?>
I'm sorry dave, I'm afraid I can't do that.
<?php $__slot = ob_get_clean();
require_once storage_path('framework/views/_lilblaze_a1b2c3d4e5f6.php');
_lilblaze_a1b2c3d4e5f6(array_merge(['type' => $type], ['slot' => $__slot])); ?>
Compare that to the 20+ lines of ComponentAttributeBag boilerplate we saw earlier. Much leaner, right? Now let's look at the three methods that make this happen.
compileNode is the entry point. It generates a unique function name from the component path, delegates to wrapComponent to produce the function file, and returns a TextNode with either a simple function call (self-closing) or an ob_start/ob_get_clean wrapper to capture slot content:
// app/LilBlaze/LilBlaze.php
private function compileNode(ComponentNode $node): ?TextNode
{
$path = resource_path("views/components/{$node->name}.blade.php");
if (! file_exists($path)) {
return null;
}
$hash = substr(md5($path), 0, 12);
$funcName = "_lilblaze_{$hash}";
$this->wrapComponent($path, $funcName);
$attrs = $this->buildAttributeArray($node->attributes);
$requirePath = "storage_path('framework/views/{$funcName}.php')";
if ($node->selfClosing) {
return new TextNode(
"<?php require_once {$requirePath}; {$funcName}({$attrs}); ?>"
);
}
$slotContent = implode('', array_map(fn ($n) => $n->render(), $node->children));
return new TextNode(
"<?php ob_start(); ?>{$slotContent}<?php \$__slot = ob_get_clean(); "
."require_once {$requirePath}; "
."{$funcName}(array_merge({$attrs}, ['slot' => \$__slot])); ?>"
);
}
wrapComponent does the heavy lifting. It reads the component's Blade source and transforms it into a plain PHP function: extract @props defaults, strip all Blade directives, convert {{ }} mustaches into <{{'?php'}} echo e(...) ?>, then wrap everything in a named function that merges defaults with the passed data:
// app/LilBlaze/LilBlaze.php
private function wrapComponent(string $sourcePath, string $funcName): void
{
$compiledPath = storage_path("framework/views/{$funcName}.php");
if (file_exists($compiledPath) && filemtime($compiledPath) >= filemtime($sourcePath)) {
return;
}
$source = file_get_contents($sourcePath);
$defaults = '[]';
if (preg_match('/@props\(\s*(\[.*?\])\s*\)/s', $source, $m)) {
$defaults = $m[1];
}
$source = preg_replace('/@\w+\(.*?\)\s*\n?/s', '', $source);
$source = preg_replace('/@\w+\s*\n?/', '', $source);
$source = preg_replace_callback(
'/\{\{\s*(.+?)\s*\}\}/s',
fn ($m) => '<?php echo e('.$m[1].'); '.'?>',
$source
);
$php = implode(PHP_EOL, [
"<?php if (!function_exists('{$funcName}')):",
"function {$funcName}(array \$__data = []) {",
" \$__data = array_merge({$defaults}, \$__data);",
' extract($__data);',
' ob_start();',
"?>{$source}<?php",
' echo ltrim(ob_get_clean());',
'}',
'endif; ?>',
'',
]);
file_put_contents($compiledPath, $php);
}
Finally, buildAttributeArray converts the raw attribute string into a PHP array literal, handling both static (key="value") and dynamic (:key="$expr") attributes:
// app/LilBlaze/LilBlaze.php
private function buildAttributeArray(string $attributes): string
{
if (empty(trim($attributes))) {
return '[]';
}
preg_match_all('/:?(\w+)="([^"]*)"/', $attributes, $matches, PREG_SET_ORDER);
if (empty($matches)) {
return '[]';
}
$pairs = array_map(function ($matching) {
$isDynamic = str_starts_with($matching[0], ':');
return $isDynamic
? "'".addslashes($matching[1])."' => ".$matching[2]
: "'".addslashes($matching[1])."' => '".addslashes($matching[2])."'";
}, $matches);
return '['.implode(', ', $pairs).']';
}
Wrapper is more comprehensive. It handles @aware, hoists use statements above the function, and runs the template through the full Blade compiler.After the walker has processed all nodes, any components that were folded need to be tracked. If the component source file changes later, the cached compiled view becomes stale. So, we need to prepend dependency markers to the output, and track them as the walker runs:
// app/LilBlaze/LilBlaze.php
private array $folded = [];
private function recordFolded(string $name, string $path): void
{
$this->folded[] = [
'name' => $name,
'path' => $path,
'mtime' => filemtime($path),
];
}
private function stamp(string $compiled): string
{
$header = '';
foreach ($this->folded as $dep) {
$header .= "<?php /* [LilBlazeFolded]:{$dep['name']}:{$dep['path']}:{$dep['mtime']} */ ?>".PHP_EOL;
}
$this->folded = [];
return $header . $compiled;
}
Blaze hooks into Laravel's composing:* view events to automatically detect stale folded dependencies and trigger recompilation.
The AppServiceProvider wires it up the same way as Smol Blaze:
// app/Providers/AppServiceProvider.php
public function register(): void
{
$this->app->singleton(LilBlaze::class);
Blade::prepareStringsForCompilationUsing(function (string $template) {
return app(LilBlaze::class)->compile($template);
});
}
Hopefully building Smol Blaze and Lil Blaze gave you a solid mental model of what Blaze does under the hood. For most apps, just installing the package and letting the Function Compiler do its thing will be enough. When you need more, folding and memoization are there.
The full Blaze pipeline is significantly more involved than what we built here. The Livewire team (especially Filip) has been hard at work making it as bulletproof and performant as possible. Perhaps someday these wins will be ported back to the mothership's (Laravel) core Blade compiler engine, but as of now I'll be installing it on every Blade-heavy Laravel app to gain some of these sweet perf wins.
Have you tried Blaze on your projects? Let us know how it's going. Until next time!
We appreciate your interest.
We will get right back to you.