Розроблення фронтенду сайту на Alpine.js
Alpine.js — мініміалістичний фреймворк для додавання реактивності прямо в HTML-розмітку. Без побудови, без віртуального DOM, без дерев компонентів. Атрибути x-data, x-bind, x-on — і у вас працює інтерфейс. Це свідомий вибір для проектів, де jQuery уже надлишковий, а React — явний overkill.
Типичні кандидати: Laravel Blade + Alpine.js, PHP-сайти з серверним рендером, WordPress з кастомними блоками, статичні сайти з невеликою інтерактивністю.
Що Alpine.js вміє з коробки
Директиви покривають 90% задач звичайного інтерфейсу:
| Директива | Призначення |
|---|---|
x-data |
Визначення реактивного стану компоненту |
x-bind / : |
Привязка атрибутів |
x-on / @ |
Обробка событій |
x-show |
Управління видимістю (display) |
x-if |
Умовний рендер (монтування/розмонтування) |
x-for |
Ітерація по масиву |
x-model |
Двостороння привязка для форм |
x-transition |
Анімації входу/виходу |
x-ref |
Доступ до DOM-елементів |
$store |
Глобальне сховище |
$fetch |
Вбудований fetch з реактивністю (через @alpinejs/morph) |
Архітектура без побудови
Для невеликих проектів Alpine.js підключається через CDN:
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
Для production-проектів з Vite:
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
build: { rollupOptions: { input: 'resources/js/app.js' } }
});
// app.js
import Alpine from 'alpinejs';
import focus from '@alpinejs/focus';
import persist from '@alpinejs/persist';
Alpine.plugin(focus);
Alpine.plugin(persist);
window.Alpine = Alpine;
Alpine.start();
Приклад: модальне вікно з анімацією
<div x-data="{ open: false }">
<button @click="open = true">Відкрити</button>
<div
x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.outside="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 flex items-center justify-center"
>
<div class="bg-white rounded-xl p-6 shadow-xl w-full max-w-md">
<h2 class="text-lg font-semibold">Заголовок</h2>
<button @click="open = false">Закрити</button>
</div>
</div>
</div>
Глобальне стан через $store
Alpine.store('cart', {
items: Alpine.$persist([]).as('cart_items'),
get count() { return this.items.length; },
get total() { return this.items.reduce((s, i) => s + i.price * i.qty, 0); },
add(product) {
const existing = this.items.find(i => i.id === product.id);
if (existing) existing.qty++;
else this.items.push({ ...product, qty: 1 });
},
remove(id) {
this.items = this.items.filter(i => i.id !== id);
}
});
У шаблоні: <span x-text="$store.cart.count"></span> — корзина оновлюється везде автоматично. @alpinejs/persist зберігає дані в localStorage між сеансами.
Інтеграція з серверним рендером
Alpine.js ідеально підходить для Laravel Blade:
{{-- resources/views/components/dropdown.blade.php --}}
<div x-data="dropdown()" class="relative">
<button @click="toggle" :aria-expanded="open">
{{ $label }}
<svg :class="{ 'rotate-180': open }" .../>
</button>
<ul x-show="open" @click.outside="close" x-transition>
@foreach($items as $item)
<li><a href="{{ $item['url'] }}">{{ $item['label'] }}</a></li>
@endforeach
</ul>
</div>
<script>
function dropdown() {
return {
open: false,
toggle() { this.open = !this.open; },
close() { this.open = false; }
}
}
</script>
Робота з AJAX та HTMX-паттернами
Alpine.js не має вбудованого HTTP-клієнта, але інтегрується з fetch нативно:
<div
x-data="{
results: [],
query: '',
loading: false,
async search() {
if (this.query.length < 2) return;
this.loading = true;
const res = await fetch(`/api/search?q=${encodeURIComponent(this.query)}`);
this.results = await res.json();
this.loading = false;
}
}"
>
<input
x-model.debounce.300ms="query"
@input="search"
placeholder="Пошук..."
/>
<div x-show="loading">Завантаження...</div>
<ul>
<template x-for="item in results" :key="item.id">
<li x-text="item.title"></li>
</template>
</ul>
</div>
Терміни та склад робіт
- Тиждень 1: налаштування побудови (Vite/CDN), інтеграція з backend-шаблонізатором, базові інтерактивні компоненти
-
Тижні 2–3: форми з валідацією, корзина/улюблене через
$store, анімації, AJAX-запити - Тиждень 4: оптимізація, тестування в браузерах, документація компонентів
Результуючий JS-бандл для середнього сайту — 15–30 KB (Alpine core + плагіни). Порівняйте з 150+ KB для React-приложення тої ж функціональності.







