Загрузка...

Laravel Blaze — пакет для оптимизации Blade-компонентов

Laravel Blaze

Введение: проблема, о которой вы не знали

Ваши Blade-компоненты медленнее, чем вы думаете. Не потому что вы написали плохой код — сам процесс рендеринга несёт накладные расходы, которые накапливаются с каждым вложенным компонентом.

Кнопка, которая рендерится за микросекунды в единичном экземпляре, становится реальным узким местом, когда вы выводите 500 таких кнопок на дашборде.

Кейлеб Порцио (создатель Livewire, Alpine.js и Flux UI) говорил об этой проблеме ещё на Laracon US 2025: даже кэшированные Blade-компоненты примерно в 10 раз медленнее чистого PHP.

В феврале 2026 года на Laravel Worldwide Meetup он запустил Laravel Blaze и продемонстрировал бенчмарк в реальном времени: 25 000 компонентов отрендерены менее чем за 17 мс.

Это и есть проблема, которую решает Blaze.


Что такое Laravel Blaze?

Laravel Blaze (пакет livewire/blaze) — это новый пакет от команды Livewire, который прекомпилирует Blade-компоненты в оптимизированные PHP-функции, полностью минуя стандартный pipeline рендеринга.

Ключевые факты

Параметр Значение
Пакет livewire/blaze
Версия v1.0.0 (beta)
Дата релиза 24 февраля 2026 года
Анонс Laracon US 2025 + Laravel Worldwide Meetup (февраль 2026)
Поддержка Laravel 10, 11, 12
Требования PHP ^8.1
Автор Caleb Porzio (команда Livewire)

Цифры из официального README

  • 500 мс → 13 мс для 25 000 компонентов
  • Снижение накладных расходов на 97%

Что Blaze делает (и чего НЕ делает)

Что оптимизирует Blaze

Blaze оптимизирует только pipeline рендеринга Blade-компонентов. Не ваши запросы к БД. Не API-вызовы. Не бизнес-логику.

Если страница тормозит из-за 2-секундного Eloquent-запроса — Blaze не поможет. Для этого нужны оптимизации на уровне базы данных.

Что именно оптимизируется

Каждый анонимный Blade-компонент проходит многоэтапный процесс:

  1. Поиск файла представления
  2. Разрешение props
  3. Слияние атрибутов
  4. Обработка слотов
  5. Компиляция шаблона
  6. Рендеринг вывода

Для одной кнопки это незаметно. Для таблицы данных с сотнями строк, каждая из которых содержит несколько вложенных компонентов? Вот тут миллисекунды и накапливаются.

Blaze заменяет весь этот pipeline на прямые вызовы PHP-функций. Шаблон компилируется один раз в оптимизированную функцию, и каждый последующий рендер просто вызывает эту функцию.

Важное ограничение

⚠️ Blaze работает ТОЛЬКО с анонимными Blade-компонентами.

Если вы используете класс-компоненты (с отдельным PHP-классом), Blaze их не оптимизирует.

Анонимные компоненты — это файлы .blade.php в resources/views/components без соответствующего класса.


Установка и базовая настройка

Шаг 1: Установка пакета

composer require livewire/blaze:^1.0@beta

Всё. Никаких конфигурационных файлов. Никакой регистрации сервис-провайдеров. Blaze автоматически обнаруживается и регистрируется.

Шаг 2: Очистка скомпилированных представлений

php artisan view:clear

Это заставит Blaze перекомпилировать всё с новым оптимизированным pipeline.

Шаг 3: Включение оптимизации

Есть два способа активировать Blaze для ваших компонентов.

Способ A: Директива @blaze для отдельных компонентов

Добавьте @blaze в начало любого компонента:

{{-- resources/views/components/button.blade.php --}}
@blaze
@props(['variant' => 'primary'])

<button type="button" class="btn btn-{{ $variant }}">
    {{ $slot }}
</button>

Способ B: Оптимизация целых директорий

Зарегистрируйте директории в сервис-провайдере:

use LivewireBlazeBlaze;

public function boot(): void
{
    Blaze::optimize()
        ->in(resource_path('views/components/ui'))
        ->in(resource_path('views/components/icons'));
}

Можно комбинировать оба подхода: начать с конкретных директорий и расширять покрытие по мере проверки совместимости.

Бонус для пользователей Flux UI

Если вы используете Flux UI (официальная библиотека компонентов Livewire), вам вообще ничего делать не нужно. Все подходящие Flux-компоненты уже помечены @blaze. Установите пакет — и ваши Flux-компоненты станут быстрее автоматически.


Три уровня оптимизации

Blaze предлагает три уровня оптимизации, каждый из которых progressively агрессивнее. Понимание различий критически важно, потому что выбор неправильного уровня для неподходящего компонента — это путь к багам.

Tier 1: Оптимизированный компилятор (по умолчанию)

Это то, что вы получаете «из коробки» при добавлении @blaze или использовании Blaze::optimize().

Что происходит: Blade-шаблоны компилируются в оптимизированные PHP-функции вместо стандартного pipeline рендеринга.

@blaze
@props(['variant' => 'primary'])

<button type="button" class="btn btn-{{ $variant }}">
    {{ $slot }}
</button>

Характеристики:

Параметр Значение
Снижение overhead До 97%
Уровень риска Очень низкий
Совместимость Почти полная с обычным Blade
Конфигурация Не требуется

Для чего подходит: Для всего. Начните здесь и оставайтесь здесь, если нет специфической причины идти дальше.


Tier 2: Мемоизация (opt-in)

Мемоизация кэширует вывод компонента. Если один и тот же компонент появляется на странице несколько раз с идентичными props — он рендерится один раз, а остальные используют кэшированный результат.

@blaze(memo: true)
@props(['name'])

<svg class="icon icon-{{ $name }}">
    <use href="#icon-{{ $name }}" />
</svg>

Представьте дашборд с 200 статусными иконками. Без мемоизации каждый <x-icon name="check" /> проходит полный цикл рендеринга, хотя вывод идентичен. С мемоизацией — один рендер, остальные — попадания в кэш.

Важное ограничение: Мемоизация работает только на компонентах без слотов. Если ваш компонент принимает {{ $slot }}, memo не применится, потому что содержимое слота меняется для каждого использования.

Для чего подходит: Иконки, аватары, бейджи и любые компоненты, которые появляются много раз с одинаковыми props.


Tier 3: Compile-Time Folding (opt-in)

Это «ядерный вариант». И в смысле «экстремально мощный», и в смысле «обращаться с крайней осторожностью».

Folding пре-рендерит компонент во время компиляции и встраивает чистый HTML прямо в родительский шаблон. Компонент перестаёт существовать в runtime. Никакого вызова функции. Никакого разрешения переменных. Никаких накладных расходов вообще.

@blaze(fold: true)
@props(['variant' => 'primary'])

<button type="button" class="btn btn-{{ $variant }}">
    {{ $slot }}
</button>

При использовании этой кнопки со статическими props:

<x-button variant="secondary">Save</x-button>

Blaze не рендерит компонент в runtime. Он буквально «запекает» вывод в ваш шаблон во время компиляции:

<button type="button" class="btn btn-secondary">Save</button>

Нулевая стоимость в runtime. Компонент просто становится HTML.

Но есть нюанс. Folding работает только когда Blaze может определить все значения во время компиляции. Если вы передаёте динамическую переменную:

<x-button :variant="$user->theme">Save</x-button>

Blaze не может свернуть это, потому что не знает, чему равен $user->theme во время компиляции. Он автоматически откатывается к функциональному компилятору (Tier 1). Никакой ошибки, никакого краша. Просто никакого преимущества folding.

Параметр Значение
Снижение overhead Полная ликвидация runtime-накладных расходов
Уровень риска Высокий
Требования Все значения должны быть известны на этапе компиляции

Для чего подходит: Только для компонентов, которые вы лично проверили на «чистоту» (см. следующий раздел).


Когда Blaze сломает ваше приложение

Автор документации Blaze включил множество предупреждений, и не зря. Folding — это функция, от которой люди будут в наибольшем восторге, и она же наиболее вероятно вызовет тонкие, трудно диагностируемые баги.

Тест на «чистоту»

Перед добавлением @blaze с folding задайте себе пять вопросов о компоненте:

  1. Работает ли одинаково для всех пользователей? (нет @auth, нет auth()->user())
  2. Работает ли одинаково на каждом запросе? (нет request(), нет @csrf)
  3. Работает ли одинаково в любое время? (нет now(), нет Carbon::now())
  4. Использует только переданные props? (нет session(), нет config(), нет запросов к БД)
  5. Все дочерние компоненты тоже foldable?

Если ответ «нет» хотя бы на один вопрос — не используйте folding для этого компонента.

Документация Blaze называет это ментальной моделью «чистой функции». Ваши @blaze-компоненты должны быть как чистые функции в программировании: одинаковый ввод всегда даёт одинаковый вывод, без побочных эффектов.


Коварные ошибки

Эти паттерны выглядят безобидно, но приведут к багам:

1. Config-значения, меняющиеся между окружениями

{{-- URL будет «запечён» во время компиляции --}}
@blaze
<a href="{{ config('app.url') }}/dashboard">
    Dashboard
</a>

Если вы компилируете представления в продакшене, config('app.url') запекается с тем значением, которое было на момент компиляции. Если потом измените .env — ссылка не обновится, пока вы не очистите скомпилированные представления. Легко пропустить.

2. Компоненты с CSRF-токенами

{{-- НИКОГДА не используйте @blaze с формами, содержащими @csrf --}}
@blaze
<form method="POST">
    @csrf
    <button type="submit">Submit</button>
</form>

CSRF-токен меняется для каждой сессии. Folding запечёт один токен навсегда. Каждая отправка формы будет падать.

3. Зависимый от времени контент

@blaze
<footer>
    &copy; {{ date('Y') }} My Company
</footer>

1 января этот футер всё ещё будет показывать прошлый год, пока вы не очистите представления.

4. Компоненты с non-foldable детьми

@blaze
<div class="card">
    <x-user-greeting /> {{-- Если этот использует auth(), родитель тоже сломается --}}
    {{ $slot }}
</div>

Folding «заразен» в обратную сторону. Родитель не может безопасно свернуться, если любой из его хардкоженных детей зависит от runtime-состояния.


Что Blaze ловит (а что — нет)

Blaze пытается защитить вас. Он выбросит исключение, когда обнаружит использование глобального состояния вроде auth(), session() или request() внутри folded-компонента.

Но документация прямо говорит: он не может поймать всё. Паттерны вроде доступа к хелпер-функции, которая внутри делает запрос к БД, или использование Blade-директивы, которая разрешается в runtime, могут проскользнуть незамеченными.

💡 Правило: Если не уверены, безопасен ли компонент для folding — не складывайте его. Дефолтный Tier 1 компилятор уже даёт 97% снижения накладных расходов. Этого, скорее всего, достаточно.


Встроенный профайлер

Blaze поставляется с профайлером, который генерирует flame charts и детализацию времени по каждому компоненту. Это по-настоящему полезно для определения, какие компоненты выигрывают от оптимизации больше всего.

Включение профайлера

Blaze::debug();

Это добавляет debug-оверлей на ваши страницы с кнопкой «Open Profiler». Профайлер показывает каждый компонент, отрендеренный во время запроса, его длительность, глубину вложенности и применённую стратегию оптимизации (compiled, folded, memoized или стандартный Blade).

Важное замечание

Профайлер хранит данные в дефолтном кэше приложения. Убедитесь, что вы не используете array-драйвер кэша в разработке. Redis или file-based кэши работают нормально.

Правильный подход к Blaze

  1. Включите профайлер первым делом
  2. Определите самые «тяжёлые» компоненты
  3. Применяйте оптимизации стратегически, а не blanket-покрытием @blaze всего подряд

Blaze vs стандартная оптимизация производительности

Будем честны об ожиданиях. Blaze решает очень специфическую проблему: накладные расходы рендеринга Blade-компонентов. Для большинства Laravel-приложений это не основной bottleneck.

Если приложение тормозит, обычные подозреваемые остаются теми же:

  • Запросы к базе данных
  • Внешние API-вызовы
  • Неоптимизированная загрузка ассетов

Где Blaze сияет

1. Компонентно-тяжёлые приложения

Если вы построили дизайн-систему с переиспользуемыми Blade-компонентами, или если вы запускаете админ-панель Filament со сложными табличными представлениями, рендерящими сотни компонентов на страницу — снижение накладных расходов реально значимо.

2. Livewire-приложения

Каждый Livewire ре-рендер триггерит рендеринг Blade-компонентов, поэтому снижение этих накладных расходов имеет компаундинг-эффект на интерактивность. Если вы рендерите сложные Livewire-таблицы или дашборды, Blaze может сделать разницу между отзывчивым и вялым интерфейсом.


Сравнение с альтернативами (2026)

Blaze vs Livewire

Параметр Blaze Livewire
Назначение Оптимизация рендеринга Blade Реактивные UI без JS-фреймворков
Что оптимизирует Только анонимные компоненты Полный цикл запроса
Runtime-нагрузка Минимальная Есть (WebSocket/polling)
Совместимость Работает внутри Livewire-views Независим от Blaze

Вердикт: Это не конкуренты. Blaze оптимизирует Blade-компоненты, которые Livewire использует внутри. Используйте вместе.

Blaze vs Inertia.js

Параметр Blaze Inertia.js
Подход Server-side рендеринг SPA без API
JS-требования Минимальные (Alpine.js) Vue/React/Svelte
SEO Из коробки Требует SSR
Компоненты Blade JS-компоненты

Вердикт: Разные парадигмы. Inertia — для SPA-опыта, Blaze — для оптимизации классического server-side рендеринга.

Blaze vs Filament

Параметр Blaze Filament
Тип Оптимизатор Admin-фреймворк
Назначение Ускорение Blade Быстрое создание админки
Совместимость Работает с Filament Использует Blade внутри

Вердикт: Filament-панели могут выиграть от Blaze, потому что они рендерят много Blade-компонентов.

Blaze vs Turbo (Hotwire)

Параметр Blaze Turbo
Назначение Оптимизация Blade SPA-подобный опыт без JS
Технология PHP-компиляция JavaScript-перехват ссылок
Сложность Низкая Средняя

Вердикт: Можно использовать вместе. Turbo для навигации, Blaze для быстрого рендеринга.


Практический пример: CRUD с Blaze

Допустим, у нас есть простая таблица пользователей с кнопками действий.

Без Blaze

{{-- resources/views/components/action-button.blade.php --}}
@props(['action', 'label', 'color' => 'blue'])

<button 
    type="button" 
    class="px-3 py-1 rounded bg-{{ $color }}-500 text-white"
    onclick="{{ $action }}"
>
    {{ $label }}
</button>

При рендеринге 100 пользователей с 3 кнопками на каждого = 300 компонентов. Каждый проходит полный pipeline.

С Blaze (Tier 1)

{{-- resources/views/components/action-button.blade.php --}}
@blaze
@props(['action', 'label', 'color' => 'blue'])

<button 
    type="button" 
    class="px-3 py-1 rounded bg-{{ $color }}-500 text-white"
    onclick="{{ $action }}"
>
    {{ $label }}
</button>

Одна строка @blaze — и 300 компонентов рендерятся через оптимизированные функции.

С Blaze + мемоизация (для иконок)

{{-- resources/views/components/icon.blade.php --}}
@blaze(memo: true)
@props(['name', 'size' => 'md'])

<svg class="icon icon-{{ $name }} icon-{{ $size }}">
    <use href="#icon-{{ $name }}" />
</svg>

Если все 100 пользователей показывают одну и ту же иконку «edit» — рендерится один раз, 99 раз берётся из кэша.


Рекомендации

Что делать

Установите пакет. Tier 1 компилятор достаточно безопасен почти для любого проекта. Соотношение риск/награда сильно перевешивает в сторону награды.

Начните только с Tier 1. Не прыгайте сразу в folding. 97% снижения накладных расходов от оптимизированного компилятора уже значимы.

Используйте мемоизацию выборочно. Если профайлер показывает компонент, рендерящийся десятки раз с идентичными props (иконки — классический пример), добавьте memo: true. Но не включайте его blanket.

Тестируйте в staging. Пакет помечен как early-stage beta (v1.0.0@beta). API может меняться, есть edge cases, которые ещё прорабатываются.

Чего НЕ делать

Не используйте folding без проверки. Только fold-компоненты, которые вы лично проверили на «чистоту». Когда сомневаетесь — skip.

Не применяйте @blaze к формам с @csrf. Это сломает отправку форм.

Не ожидайте miracles от медленных запросов. Blaze не ускорит ваши Eloquent-запросы.

Не используйте array-кэш с профайлером. Данные не сохранятся между запросами.


FAQ

Работает ли Blaze с Livewire-компонентами?

Blaze специально разработан для анонимных Blade-компонентов, не для Livewire-компонентов напрямую. Но поскольку Livewire-компоненты рендерят Blade-шаблоны внутри, оптимизация Blade-компонентов в ваших Livewire-views положительно влияет на общую производительность Livewire.

Будет ли Blaze конфликтовать с моим текущим Blade-setup?

Нет. Tier 1 компилятор — это drop-in замена, которая поддерживает feature parity со стандартным Blade. Если возникнут проблемы, можно убрать директиву @blaze или удалить пакет целиком — всё вернётся к норме.

Как понять, что Blaze реально помогает моему приложению?

Используйте встроенный профайлер (Blaze::debug()). Он показывает timing по каждому компоненту и применённую стратегию оптимизации. Сравните времена рендеринга с Blaze и без, чтобы измерить реальный impact на ваше конкретное приложение.

Работает ли Blaze с Laravel 10?

Да. Blaze поддерживает Laravel 10, 11 и 12 и требует PHP 8.1 или выше.

Можно ли использовать Blaze в продакшене?

Tier 1 оптимизированный компилятор безопасен для продакшена. Пакет помечен как beta, но основная стратегия компиляции хорошо протестирована. Folding (Tier 3) требует более тщательной валидации перед деплоем в прод. Всегда тестируйте тщательно в staging-окружении.


Заключение

Blaze решает проблему, о которой большинство Laravel-разработчиков даже не знали. Накладные расходы рендеринга Blade-компонентов невидимы, пока у вас не станет достаточно компонентов, чтобы это стало заметно — и к тому моменту вы обычно вините что-то другое.

То, что это one-line install с немедленными преимуществами (Tier 1) и опциональными продвинутыми функциями (мемоизация, folding) для случаев, когда они нужны — делает его лёгкой рекомендацией.

Просто не слишком увлекайтесь folding, пока не поймёте все его последствия.

Если вы строите что-то компонентно-тяжёлое и производительность важна — попробуйте Blaze. Это один из тех редких пакетов, который даёт реальный прирост производительности практически бесплатно.


Резюме в одной таблице

Уровень Команда Снижение overhead Риск Когда использовать
Tier 1 @blaze До 97% Низкий Всегда, для всех анонимных компонентов
Tier 2 @blaze(memo: true) Кэширование идентичных Низкий Иконки, бейджи — компоненты без слотов
Tier 3 @blaze(fold: true) 100% (нулевой runtime) Высокий Только проверенные «чистые» компоненты

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *