Первый компонент: один файл .svelte

Файл .svelte — это один компонент: скрипт, разметка и стили в одном месте, как HTML, но с суперспособностями.

«Один компонент — один файл.» Это правило делает Svelte-проекты предсказуемыми: вы всегда знаете, где искать логику, разметку и стиль конкретного блока интерфейса.

Базовая единица Svelte — компонент, и живёт он в файле с расширением .svelte. Такой файл состоит из трёх необязательных частей: блок script с логикой на JavaScript, разметка (обычный HTML с добавками Svelte) и блок style с CSS. Все три части описывают один кусок интерфейса. Это похоже на однофайловые компоненты Vue, но синтаксис ближе к чистому HTML.

Самое приятное — насколько мало кода нужно для рабочего компонента. Объявите переменную в скрипте, и вы тут же можете вставить её в разметку через фигурные скобки. Никаких шаблонных движков со своим языком, никаких директив для простого вывода значения. Если переменная реактивная (об этом — следующий раздел), интерфейс сам обновится при её изменении.

Посмотрим на классический первый компонент — счётчик. Обратите внимание: код для нажатия выглядит как обычное присваивание, потому что так и есть.

<script>
  let count = $state(0);

  function increment() {
    count += 1;
  }
</script>

<button onclick={increment}>
  Нажали раз: {count}
</button>

<style>
  button { font-size: 1.2rem; padding: 0.5rem 1rem; }
</style>

Здесь $state(0) — это руна, делающая переменную реактивной (подробно в следующем разделе). Выражение {count} в разметке вставляет текущее значение. Обработчик onclick — это обычный DOM-атрибут события, а не специальная директива. И стили в блоке style по умолчанию изолированы: они применятся только к этому компоненту, а не утекут на весь сайт.

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

Компилятор Svelte разбирает этот файл и превращает его в JavaScript-функцию, которая создаёт элементы, навешивает обработчик и — главное — запоминает, что текстовый узел внутри кнопки зависит от count. Когда count меняется, генерируется вызов, обновляющий ровно этот текст. Стили компилятор переписывает, добавляя к селекторам уникальный хеш-класс, чтобы добиться изоляции без дополнительных усилий с вашей стороны.

  Counter.svelte                компилятор              браузер
  -----------------             ----------              ----------
  <script> count </script>  ->  create_fragment() ->  <button>...</button>
  <button>{count}</button>  ->  update(count)     ->  textNode.data = count
  <style> button {} </style> ->  .button.svelte-x  ->  изолированный CSS

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

  • Пытаться импортировать .svelte как обычный JS-модуль и запускать в Node. Файл нужно сначала скомпилировать сборщиком (Vite).
  • Забыть про $state в Svelte 5. Простое let count = 0 в рантайм-режиме не будет реактивным.
  • Ожидать, что стили глобальны. По умолчанию они изолированы; для глобальных нужен модификатор :global(...).

Best practices

  • Держите компоненты маленькими и сфокусированными на одной задаче — так их легче переиспользовать.
  • Имена файлов компонентов пишите с заглавной: Counter.svelte, UserCard.svelte.
  • Используйте изоляцию стилей как преимущество: не бойтесь простых селекторов вроде button — они не утекут наружу.

От одного компонента к приложению

Один компонент-счётчик кажется игрушкой, но именно из таких кирпичиков складываются настоящие интерфейсы. Реальное приложение — это десятки и сотни компонентов, каждый из которых отвечает за свой маленький кусок: кнопка, карточка товара, форма входа, список комментариев. Компоненты импортируют друг друга и вкладываются один в другой, образуя дерево. Поскольку каждый компонент изолирован — его стили не утекают, его состояние локально, — вы можете рассуждать о нём отдельно, не держа в голове весь проект. Это и есть главная ценность компонентного подхода: сложность разбивается на управляемые части. Когда вы привыкнете мыслить компонентами, проектирование интерфейса превратится в вопрос «из каких блоков он состоит и как они общаются», а не «как написать одну гигантскую страницу».

Итог: компонент Svelte — это один .svelte-файл со скриптом, разметкой и стилями. Переменные вставляются в разметку фигурными скобками, события вешаются как обычные DOM-атрибуты, а стили изолированы по умолчанию.

Проверьте себя
1. Из каких частей состоит файл .svelte?
AТолько из HTML-разметки
BИз блока script, разметки и блока style — все необязательны
CИз JSON-конфигурации и стилей
DИз отдельных файлов для логики и шаблона
2. Что по умолчанию происходит со стилями в блоке style компонента?
AОни применяются глобально ко всему сайту
BОни игнорируются при сборке
CОни изолированы и действуют только в пределах этого компонента
DОни конвертируются в inline-стили на каждом элементе