Формы и form actions

Form actions в +page.server.js обрабатывают отправку форм на сервере и работают даже без JavaScript.

«Если load читает данные с сервера, то actions их записывают.» Формы в SvelteKit устойчивы: они работают и без JS, и лучше с ним.

Загрузчик load читает данные, а как их записывать — создавать пост, логиниться, оставлять комментарий? Для этого в SvelteKit есть form actions. В файле +page.server.js вы экспортируете объект actions с функциями-обработчиками отправки формы. Браузер шлёт обычный POST-запрос формы, сервер его обрабатывает.

Ключевая идея — прогрессивное улучшение. Форма работает на чистом HTML без единой строчки JavaScript: браузер отправляет данные, сервер отвечает. А если JavaScript есть, директива use:enhance перехватывает отправку и делает её без перезагрузки страницы, плавно. То есть базовая функциональность доступна всем, а улучшения — поверх. Это делает приложение надёжнее.

// src/routes/contact/+page.server.js
import { fail } from '@sveltejs/kit';

export const actions = {
  default: async ({ request }) => {
    const data = await request.formData();
    const email = data.get('email');
    if (!email) return fail(400, { error: 'Email обязателен' });
    await saveContact(email);
    return { success: true };
  }
};
<!-- src/routes/contact/+page.svelte -->
<script>
  import { enhance } from '$app/forms';
  let { form } = $props(); // результат action
</script>

<form method="POST" use:enhance>
  <input name="email" type="email" />
  <button>Отправить</button>
</form>
{#if form?.error}<p>{form.error}</p>{/if}
{#if form?.success}<p>Спасибо!</p>{/if}

Внутри action используют служебные функции: fail(status, data) возвращает ошибку валидации с данными для повторного показа формы, redirect(status, location) уводит на другую страницу, error(status, message) бросает ошибку. Можно объявить несколько именованных действий (например, login и register) и выбирать их атрибутом action у формы.

Как это работает под капотом

Форма с method="POST" отправляет данные на тот же URL, SvelteKit находит нужный action, выполняет его и либо возвращает результат в проп form, либо делает редирект. Смоделируем обработку отправки с валидацией.

// Обработка form action: валидация -> успех или fail
function fail(status, data) { return { status, ...data, ok: false }; }
async function action(formData) {
  const email = formData.email;
  if (!email) return fail(400, { error: 'Email обязателен' });
  if (!email.includes('@')) return fail(400, { error: 'Неверный email' });
  return { status: 200, success: true, ok: true };
}

action({}).then(r => console.log(r));                    // {error: 'Email обязателен'}
action({ email: 'нет' }).then(r => console.log(r));      // {error: 'Неверный email'}
action({ email: '[email protected]' }).then(r => console.log(r));   // {success: true}

Попробуй сам ▶ — вставь код в консоль браузера (F12 → Console) и нажми Enter, чтобы увидеть вывод.

  <form method=POST use:enhance>
        |
        v
  actions в +page.server.js
        |
        +-- ошибка -> fail() -> проп form (показать сообщение)
        +-- успех  -> данные или redirect()
  (без JS — то же, но с перезагрузкой страницы)

Частые ошибки

  • Возвращать ошибку валидации через throw вместо fail. fail сохраняет данные формы для повторного показа.
  • Забыть method="POST" у формы. Без него action не вызовется.
  • Полагаться только на JS-валидацию. Проверяйте данные на сервере — это безопаснее.

Best practices

  • Добавляйте use:enhance для плавного UX, но не ломайте работу без JS.
  • Валидируйте на сервере и возвращайте fail с понятными сообщениями.
  • Для многошаговых сценариев используйте именованные actions.

Почему прогрессивное улучшение важно

Идея, что форма должна работать без JavaScript, в эпоху одностраничных приложений может показаться старомодной — но за ней стоит серьёзная инженерная мудрость. JavaScript на странице может не загрузиться: оборвалась сеть, скрипт упал с ошибкой, пользователь сидит за корпоративным прокси, который что-то вырезал. Если ваша форма построена как нативная HTML-форма с серверным action, она продолжит работать даже в этих условиях — браузер просто отправит данные обычным запросом. А когда JavaScript есть, директива use:enhance бесшовно перехватывает отправку и делает её плавной, без перезагрузки. Так вы получаете лучшее из двух миров: надёжную базу, доступную всем, и приятный UX поверх неё для большинства. Этот подход также дисциплинирует: раз форма обязана работать через сервер, вы неизбежно пишете серверную валидацию, а не полагаетесь только на клиентскую, которую легко обойти. В итоге приложение получается и доступнее, и безопаснее.

Итог: form actions обрабатывают отправку форм на сервере, работают без JavaScript и улучшаются через use:enhance. Используйте fail, redirect и error для управления результатом.

Проверьте себя
1. Где определяются form actions в SvelteKit?
AВ +page.svelte
BВ экспорте actions из +page.server.js
CВ svelte.config.js
DВ отдельном файле routes.json
2. В чём смысл прогрессивного улучшения форм в SvelteKit?
AФорма работает только при включённом JavaScript
BФорма работает на чистом HTML без JS, а use:enhance улучшает UX, когда JS доступен
CФорма автоматически шифрует данные
DФорма отправляется только через GET