Скажу сразу: Alpine.js — это реактивность, но в мини-формате. Отлично работает на статике и в простых SPA. Но как только начинаешь говорить «серверный рендеринг», появляется легкая морока.
Почему? Alpine изначально живёт в браузере. На сервере он не считает состояния, не рендерит события, не ставит x-data и x-on сам. Сервер должен просто отдать правильный HTML, а Alpine потом оживит его. Иначе будешь сидеть и ломать голову, почему интерактивность не работает.
Шаг 1: Установка Alpine.js
Если npm в проекте — ставим командой:
npm install alpinejs
Да, банально. Если используешь CDN — просто вставь <script src="https://unpkg.com/alpinejs" defer></script> в HTML. Главное, чтобы Alpine загружался после DOM.
Шаг 2: Подготовка серверного HTML
Сервер должен отдавать HTML с нужными атрибутами:
x-data— состояние компонентаx-bind— биндыx-on— события
Без них Alpine просто не знает, что делать.
Пример:
<div x-data="{ count: 0 }">
<button x-on:click="count++">+</button>
<span x-text="count"></span>
</div>
На сервере это просто статический HTML. Alpine оживляет его на клиенте.
Шаг 3: Инициализация на клиенте
После того как сервер отдал HTML, нужно стартануть Alpine:
<script src="/path/to/alpine.js" defer></script>
<script>
document.addEventListener("DOMContentLoaded", () => { Alpine.start(); });
</script>
defer важен, иначе Alpine попытается работать до того, как DOM загрузился — и будут ошибки.
Пример на Node.js + Express
Предположим, есть простой сервер:
const express = require('express');
const app = express();
const fs = require('fs');
const path = require('path');
app.get('/', (req, res) => {
fs.readFile(path.join(__dirname, 'index.html'), 'utf8', (err, data) => {
if (err) return res.status(500).send('Server Error');
const alpineScript = '<script src="/path/to/alpine.js" defer></script>';
const alpineInit = '<script>document.addEventListener("DOMContentLoaded", () => { Alpine.start(); });</script>';
const htmlWithAlpine = data.replace('</body>', `${alpineScript}${alpineInit}</body>`);
res.send(htmlWithAlpine);
});
});
app.listen(3000, () => console.log('Server running on port 3000'));
Суть: сервер читает HTML, вставляет скрипт Alpine.js и инициализацию, отдает браузеру. Всё. Никаких магических SSR-фич Alpine на сервере нет.
Лайфхаки и подводные камни
- Состояние на сервере не считает Alpine. Всё, что нужно для интерактивности — в HTML или потом через JS.
- Динамические данные лучше вставлять через шаблонизатор (Blade, EJS, Pug) или через JSON, который Alpine подхватывает.
- События до загрузки DOM ломают всё. Всегда
deferиDOMContentLoaded. - SSR в Alpine — это условное SSR. Ты отдаёшь HTML с начальными значениями, а Alpine делает интерактивность уже в браузере. Настоящий SSR как в Vue/Nuxt или React/Next.js Alpine не умеет.
Итог
Alpine.js с серверным рендерингом — это всегда компромисс. Ты не получаешь полноценного SSR, но можешь отдавать HTML, который Alpine потом оживит на клиенте.
Если хочешь настоящего SSR с реактивностью — придётся смотреть на Vue, React или Svelte. Alpine — это лёгкая, простая и удобная штука для небольших проектов или для добавления интерактивности к статике.
0 комментариев