Fusion, або мистецтво написання PHP у Vue SFC-компоненти.

Перекладено ШІ 0 Laravel News 26 червня, 2026

Чи готові ви писати PHP-код безпосередньо всередині Vue SFC для миттєвого зв’язку з бекендом? Проєкт Fusion пропонує революційний підхід, що кардинально змінює правила гри в екосистемі Laravel.

Це справді особлива стаття.

Два тижні тому, 3–4 лютого 2025 року, в Амстердамі пройшла конференція Laracon EU. Хоча я не зміг бути там особисто, я уважно стежив за подією через стрім. Такі конференції — це завжди шанс отримати свіжі інсайди та ще глибше зануритися в неймовірну ecosystem Laravel. Сподіваюся, колись я все ж потраплю на Laracon наживо.

Особливо мою увагу привернула доповідь Aaron Francis«Introducing [REDACTED]: A New Paradigm for Laravel + Javascript». Це заінтригувало, адже ми вже маємо Inertia та Livewire — чудові інструменти для сучасних додатків на Laravel. Що ж нового можна запропонувати?

Аарон представив Fusion — інноваційний підхід до інтеграції фронтенду з Laravel-бекендом. Ідея в тому, щоб писати PHP-код безпосередньо у файлі фронтенду. Після обробки цей PHP виконується на стороні сервера, а результати передаються на клієнт. Це нагадує Inertia, але йде значно далі.

Обов'язково подивіться відео. Воно захоплює, легко сприймається і допоможе краще зрозуміти решту цієї статті.

У інтерв'ю для подкасту Navbar Аарон пояснив мету Fusion: стерти межу між фронтендом та бекендом, спростити розробку та наблизити Laravel з Inertia до можливостей сучасних meta-frameworks на кшталт Next або Nuxt. Разом зі своїм партнером Steve Аарон помітив, що звичні для Laravel концепції (як-от роути у web.php) не завжди інтуїтивні для JavaScript-розробників, які звикли до file-based routing. Fusion має зробити Laravel доступнішим для JS-спільноти.

Завдяки Fusion у Vue SFC з'являється новий блок для PHP-коду, що робить його невід'ємною частиною додатка.

<php>
  // Визначаємо prop на PHP
  $name = prop(Auth::user()->name);
</php>
 
<template>
  <!-- Використовуємо його у Vue! -->
  Hello {{ name }}!
</template>

Ця стаття не про те, чи варто використовувати Fusion у продакшені або чи етично писати PHP всередині Vue SFC. Ці дискусії вже активно точаться на X та Reddit.

Натомість я хочу розібратися, як Fusion працює «під капотом», з двох причин:

  1. Аналіз чужого коду — найкращий спосіб навчання. Я часто вивчаю кодові бази проектів, щоб знайти цікаві прийоми та патерни, які інші могли пропустити.
  2. Fusion — це технічний пік того, чого можна досягти за допомогою Laravel, Vue та Vite. Мені було щиро цікаво зрозуміти його механіку. Аналогічно я вивчаю бібліотеку Alien Signals від Johnson Chu. А щоб розібратися в чомусь досконало, варто спробувати пояснити це іншим.

Інтеграція Vite з Laravel просто неймовірна. Якщо ви ще не дослідили можливості Vite, обов'язково зробіть це.

А тепер зануримося в код.

Вивчати цей codebase дуже цікаво — це схоже на читання PHP, написаного мовою JavaScript.

# Codebase проекту Fusion

Через тиждень після Laracon EU Аарон відкрив код Fusion. Мені здавалося, що все тримається на плагіні Vite, який витягує PHP із Vue SFC, подібно до того, як стандартний плагін Vue обробляє script, template та style.

Для Vite підтримка HTML, CSS та JavaScript є природною. Однак PHP — це виклик, оскільки Vite не підтримує його «з коробки».

Давайте сформулюємо питання, на які ми знайдемо відповіді. Перше: як саме Fusion керує PHP-кодом?

Hype-відео Fusion від Aaron Francis та Steve Tenuto, доступне в X.

Переглядаючи промо-відео, стає зрозуміло: Fusion робить більше, ніж просто витягує код. Він передає результати PHP-коду як props у Vue-компонент і підтримує RPC-виклики до Laravel-бекенда прямо з клієнта. Крім того, ключове слово sync дозволяє синхронізувати стан між фронтендом і бекендом.

Наприклад, функція favorite стає доступною на фронтенді миттєво:

<php>
use function \Fusion\{prop, expose};
use \App\Models\Podcast;
 
$podcasts = prop(fn () => Podcast::all())->readonly();
 
expose(favorite: fn (Podcast $podcast) => response()->json($podcast->toggleFavorite()));
</php>
 
<script lang="ts" setup>
import Podcast from '@Components/Podcast.vue'
</script>
 
<template>
  <Podcast
    v-for="podcast in podcasts"
    :key="podcast.id"
    v-bind="podcast"
    @favorite="favorite({ podcast }).then(fav => podcast.favorited = fav)"
  />
</template>

Виникає друге питання: які механізми працюють за лаштунками, щоб усе це стало можливим?

І нарешті: Fusion позиціонується як інструмент, що виводить Inertia на новий рівень. Отже, як саме Fusion використовує Inertia?

Розберемося по черзі.

# Як Fusion керує PHP-кодом?

Усе починається з Vite. Як і завжди.

Для тих, хто не в курсі: Vite — це надшвидкий інструмент збірки фронтенду. Його філософія — обробка «на вимогу» (on-demand). Vite виступає проксі-сервером між браузером і файловою системою. Коли браузер запитує файл, Vite перехоплює запит, трансформує код, ін'єктує потрібні фрагменти або навіть генерує віртуальні файли. Завдяки системі плагінів Vite можна адаптувати під будь-які потреби.

Ось як Vite зазвичай обробляє файл SFC:

<script setup>
// JavaScript код
</script>
 
<template>
  <div />
</template>
 
<style scoped>
  /* CSS код */
</style>

Коли браузер запитує .vue файл, плагін vite-plugin-vue перетворює його на валідний JavaScript. CSS виноситься в окремий потік обробки. За допомогою плагіна vite-plugin-inspect можна побачити цей процес крок за кроком.

У Fusion відбувається те саме, але додається обробка PHP-блоку. Коли запит надходить на Vite, плагін fusion-vue активує функцію transform:

function transform(code, filename) {
  if (!filename.endsWith('.vue')) {
    return code
  }
 
  return new Transformer({
    config: fusionConfig,
    code,
    filename,
    isProd
  }).transform()
}

Клас Transformer виконує наступні завдання:

  1. Витягує PHP-блок із Vue SFC за допомогою парсера @vue/compiler-sfc. До речі, подібний підхід використовує Vue I18n для своїх блоків перекладів.
import { parse } from '@vue/compiler-sfc'
 
const descriptor = parse(code, { filename }).descriptor
const php = descriptor.customBlocks.find(block => block.type === 'php')
  1. Видаляє PHP-блок з оригінального файлу, щоб він не заважав подальшій обробці Vue.
  2. Перевіряє актуальність коду. Якщо код не змінився (перевірка за хешем), трансформація пропускається.
  3. Валідує та зберігає PHP. Для цього викликається Laravel-команда:
await runPhp(['fusion:conform', this.relativeFilename])

Якщо в PHP-коді є помилка, Vite перехоплює її та виводить інформативне повідомлення прямо в браузері.

Якщо все добре, PHP-код зберігається в папці storage як окремий файл.

  1. Створює JavaScript-файл (shim). Цей файл є «містком» між фронтендом та PHP-частиною. Тут знову викликається Laravel:
await runPhp(['fusion:shim', this.relativeFilename])
  1. Повертає трансформований код у Vite для завершення збірки.

Це створює певну складність. Fusion працює як file-based router: перший запит йде на PHP-сервер, який віддає початковий код, а вже потім браузер звертається до Vite. Але якщо ми ще не відвідали маршрут, відповідного PHP-файлу в storage може не існувати. Щоб вирішити це, Fusion використовує власний watcher.

Vite-плагін Fusion робить дві важливі речі через watcher (Chokidar):

  1. Очищує застарілі файли у storage при видаленні компонентів.
  2. Запускає трансформацію при зміні файлів, не чекаючи запиту від браузера. Це гарантує, що PHP-файли завжди готові до роботи, навіть якщо ви щойно створили новий роут.

Ось загальна схема процесу:

# Що відбувається на стороні PHP?

Після того як Vite витягнув PHP-код, його потрібно інтегрувати в екосистему Laravel. Цим займається команда fusion:conform.

# Обробка та трансформація PHP

Код, витягнутий із SFC, не може бути виконаний просто так — його потрібно перетворити на повноцінний клас. Fusion використовує серію «трансформерів» (на базі PHP Parser), які крок за кроком змінюють код:

  • Procedural Transformer: перетворює процедурний код на метод runProceduralCode анонімного класу.
  • Props Transformer: замінює виклики prop() на внутрішні методи класу.
  • Anonymous Class Transformer: створює іменований клас у спеціальному просторі імен Fusion\Generated.

Результатом є клас, що успадковує FusionPage. Він діє як міні-контролер, що обробляє логіку конкретної сторінки та синхронізує змінні між сервером і клієнтом.

# База даних Fusion

Fusion використовує окрему базу даних SQLite (fusion.sqlite), щоб координувати роботу PHP та JavaScript. Там зберігаються зв'язки між шляхами до SFC-файлів, згенерованими класами та хешами коду. Fusion реєструє окреме з'єднання __fusion, тому це ніяк не впливає на основну базу вашого додатка.

# Обробка запитів та роль Inertia

Fusion автоматично реєструє роути для всіх SFC у resources/js/Pages. Коли ви заходите на сторінку, FusionController вирішує, що робити:

  1. Для звичайного запиту — рендерить сторінку через Inertia.
  2. Для RPC-запитів (через expose) або синхронізації — повертає JSON.

Fusion ін'єктує у ваш Vue-компонент спеціальний script setup, який містить composable useFusion. Це дозволяє прозоро використовувати змінні та функції, визначені в PHP-блоці, так само як звичайні JS-змінні.

# Підсумки

Fusion має великий потенціал, особливо для розробників, які переходять з Nuxt/Next на Laravel. Він зберігає звичний досвід (file-based routing, RPC), але додає потужність Laravel.

Цей проект демонструє, наскільки глибокою може бути синергія Vite та Laravel. Fusion не намагається замінити Inertia — він використовує її як надійний фундамент, зосереджуючись на інноваціях у самій структурі коду.

Дослідження цього проекту було справжньою пригодою. Сподіваюся, цей аналіз відкрив для вас щось нове!

# Ще дещо

Під час написання статті я помітив, що для PHP-блоків у Vue SFC немає підсвічування синтаксису. Оскільки мій сайт використовує Shiki та TextMate grammars, я вирішив це виправити.

Я створив розширення для VSCode, яке додає підтримку блоків <php> у файлах .vue. Ви можете знайти його на marketplace. Тепер писати Fusion-компоненти значно приємніше!

Успішного кодингу! 👨‍💻

Популярні

Інше, що варто прочитати

13 Оновлено 26 червня, 2026

Локальні моделі та їх скоупи в Laravel за допомогою атрибута Scope

В Laravel 12 ми отримали можливість використовувати новий підхід для визначення локальних скоупів у моделях Eloquent. Дізнайтеся, як новий атрибут #[Scope] спрощує цей процес і зберігає ваші назви методів незмінними

14 Оновлено 26 червня, 2026

Claude Agent тепер інтегрований в AI Assistant для PhpStorm

Ви коли-небудь задумувалися, як полегшити свою роботу в Laravel? У нашій статті ми розглядаємо, як інтеграція Claude Code в PhpStorm може підвищити вашу продуктивність, спростивши процес написання коду та навчання нових розробників. Читайте далі, щоб дізнатися більше про переваги та функціональність цього потужного поєднання

16 Оновлено 26 червня, 2026

Журнал аудиту в Laravel

Хочете забезпечити повну прозорість у своїх Laravel-додатках? Пакет Laravel Audit Log допоможе вам детально відстежувати всі зміни моделей Eloquent та відповідати вимогам регуляторів. Читайте далі, щоб дізнатися, як цей потужний інструмент може підвищити надійність вашого проєкту