Современная интеграция JavaScript в Laravel с использованием Vite, Livewire и Inertia
Основные подходы к интеграции JavaScript в Laravel
Эффективное решение: использование Vite и data-атрибутов
В современных версиях Laravel (начиная с 9) основным инструментом для сборки JavaScript и CSS является Vite. Он обеспечивает быструю горячую перезагрузку, модульность и оптимизацию. Для передачи данных из PHP в JavaScript рекомендуется использовать data-атрибуты в HTML или встроенные JSON-скрипты. Это исключает прямую интерполяцию в JavaScript-коде и снижает риск XSS.
{{-- Blade-шаблон --}}
Php js laravel (laravel и javascript)
Пояснение: атрибуты data- ... автоматически становятся доступными через dataset. json_encode экранирует специальные символы. При использовании Vite скрипты подключаются через @vite('resources/js/app.js') и могут обрабатываться как модули.
Типичная ошибка:
Прямая вставка PHP-переменной в JavaScript без экранирования: var name = '{{ $name }}'; - приводит к XSS, если $name содержит кавычки. Решение: использовать @json или json_encode с data-атрибутами, а также функцию js_escape() или Javascript::encode() из пакетов.
Как передать массив или коллекцию в JavaScript без ручного кодирования?
В Laravel доступна директива Blade @json, которая автоматически экранирует данные и преобразует их в JSON. Это удобно для простых переменных.
Проблема: @json выводит JSON прямо в JavaScript-контекст. Если данные содержат HTML-теги, они экранируются, но это не защищает от XSS при неправильном использовании. Всегда используйте @json только для данных, а не для пользовательского ввода, который будет интерпретироваться как HTML.
Как организовать реактивное взаимодействие без перезагрузки страницы (Livewire)?
Laravel Livewire - это полноценный фреймворк для создания динамических интерфейсов на серверном рендеринге. Он автоматически обновляет части страницы через AJAX, используя Alpine.js или собственный JavaScript.
// Компонент Livewire (app/Http/Livewire/Counter.php)
class Counter extends Component
{
public $count = 0;
public function increment()
{
$this->count++;
}
public function render()
{
return view('livewire.counter');
}
}
{{-- blade-шаблон --}}
{{ $count }}
Пояснение: Livewire использует wire:click для привязки события. Всё обновление происходит через AJAX, JavaScript-код не требуется писать вручную. Подходит для простых CRUD, форм, фильтров.
Ошибка: Неправильная установка Livewire (не выполнена команда php artisan livewire:install или отсутствует подключение пакета). Симптом: кнопка не реагирует. Решение: проверить установку и наличие @livewireStyles, @livewireScripts и скрипта Alpine.js.
Как построить SPA на основе Laravel и Vue/React (Inertia.js)?
Inertia.js - это адаптер, позволяющий использовать современный фронтенд (Vue, React, Svelte) без создания отдельного REST API. Данные передаются вместе с HTML-ответом в виде JSON-свойства «page».
// routes/web.php
Route::get('/dashboard', function () {
return Inertia\Inertia::render('Dashboard', [
'users' => User::all()
]);
});
// resources/js/Pages/Dashboard.vue
{{ user.name }}
Пояснение: Inertia автоматически сериализует данные и передаёт их в компонент. Навигация и обновление данных происходит без полной перезагрузки.
Типичная проблема: Неверно указан адаптер (например, используется React вместо Vue в конфиге). Решение: проверить файл app/Providers/AppServiceProvider.php и установить соответствующий пакет (inertiajs/inertia-laravel + inertiajs/inertia-vue3).
Как отправлять AJAX-запросы в Laravel из внешнего JavaScript-приложения?
Использовать Axios (встроен в Laravel Breeze/ Jetstream) или Fetch API. Для аутентификации используется CSRF-токен, который Laravel автоматически передаёт через куки или meta-тег.
// resources/js/bootstrap.js
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// Использование
axios.get('/api/user').then(response => {
console.log(response.data);
});
Пояснение: Для API-маршрутов (routes/api.php) не требуется CSRF-защита, если используется аутентификация через Bearer-токен. Для веб-маршрутов необходимо передавать токен через мета-тег или куки.
Ошибка: 419 ошибка (CSRF token mismatch). Решение: добавить в скрипты получение токена из meta-тега и включение его в заголовки Axios:
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
}
Расширенные примеры интеграции JavaScript в Laravel
Пример 1. Динамический поиск с использованием Livewire и Alpine.js
Создадим компонент поиска, который отправляет запрос на сервер при вводе текста и отображает результаты без перезагрузки.
// app/Http/Livewire/Search.php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Post;
class Search extends Component
{
public $query = '';
public $posts = [];
public function updatedQuery()
{
$this->posts = Post::where('title', 'like', '%'.$this->query.'%')
->take(5)
->get();
}
public function render()
{
return view('livewire.search');
}
}
{{-- resources/views/livewire/search.blade.php --}}
@foreach($posts as $post)
- {{ $post->title }}
@endforeach
Результат: при вводе текста с задержкой 300 мс выполняется AJAX-запрос, обновляется список.
(пользователь вводит 'laravel')
- Laravel для начинающих
- Интеграция Laravel и React
Пример 2. Передача сложных объектов через data-атрибуты
Передадим вложенные данные с помощью сериализации и разберём на клиенте.
// Blade
@php
$nested = [
'user' => ['name' => 'Анна', 'age' => 30],
'meta' => ['theme' => 'light', 'locale' => 'ru']
];
@endphp
Вывод в консоль: Анна
Пример 3. Использование Axios с защитой CSRF в SPA на Vue (Breeze)
Laravel Breeze устанавливает скрипты для обработки CSRF. Пример отправки формы через Axios.
{{-- В blade шаблоне --}}
// resources/js/components/LoginForm.vue
Пояснение: Axios автоматически считывает CSRF-токен из meta-тега, если он настроен в bootstrap.js. Возможная ошибка: токен не передан при первом запросе - необходимо убедиться, что meta-тег присутствует на странице.
Пример 4. Inertia.js: работа с сессионными flash-сообщениями
Inertia поддерживает flash-сообщения, которые отправляются вместе с ответом. Пример на сервере:
// контроллер
public function store(Request $request)
{
// ... логика
return redirect()->back()->with('success', 'Данные сохранены!');
}
Во vue-компоненте flash-сообщения доступны через свойство $page.props.flash:
{{ $page.props.flash.success }}
Пример вывода: если произошло сохранение, на странице появится зелёное сообщение.
(после редиректа)Данные сохранены!
Пример 5. Использование библиотеки Laravel Echo и Pusher для реального времени
Интеграция с WebSockets через Laravel Echo. Необходимо установить pusher/pusher-php-server и laravel-echo.
// config/broadcasting.php
'default' => env('BROADCAST_DRIVER', 'pusher'),
// ресурс bootstrap.js
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
forceTLS: true
});
// прослушивание события
Echo.channel('orders')
.listen('OrderShipped', (e) => {
console.log('Заказ отправлен:', e.order);
});
Результат: при вызове события OrderShipped на сервере, все подключённые клиенты получат уведомление.
Консоль: "Заказ отправлен: { id: 42, status: 'shipped' }"
Пример 6. Ленивая загрузка больших JavaScript-файлов через динамические импорты
Vite поддерживает динамические импорты, которые разбивают код на части. В Laravel это работает из коробки.
// resources/js/components/HeavyComponent.js
export default function() {
console.log('Тяжелый компонент загружен');
}
// resources/js/app.js
import('/components/HeavyComponent.js').then(module => {
module.default();
});
При сборке Vite создаст отдельный чанк для HeavyComponent. Он загрузится только при выполнении импорта.
(в консоли) "Тяжелый компонент загружен"