Svelte

Svelte представляет собой компилируемый фронтенд-фреймворк, в котором значительная часть работы переносится на этап сборки. В отличие от классических библиотек, использующих виртуальный DOM, подход основан на компиляции компонентов в оптимизированный JavaScript-код, минимизирующий накладные расходы во время выполнения.


Ключевая особенность заключается в том, что компонент преобразуется в императивные инструкции обновления DOM. Это исключает необходимость дифф-алгоритма виртуального DOM.

Процесс компиляции включает:

  • парсинг .svelte файлов;
  • анализ реактивных зависимостей;
  • генерацию оптимизированного JavaScript;
  • создание точечных обновлений DOM без промежуточного представления.

Результатом становится код, который напрямую управляет DOM-узлами, обновляя только изменённые части интерфейса.


Структура компонента

Компонент в Svelte состоит из трёх основных секций:

  • <script> — логика и состояние
  • HTML-разметка — шаблон
  • <style> — локальные стили

Пример базового компонента:

<script>
  let count = 0;

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

<button on:click={increment}>
  Счётчик: {count}
</button>

<style>
  button {
    padding: 8px 12px;
    border-radius: 6px;
  }
</style>

Переменная count автоматически связана с интерфейсом без необходимости ручного вызова функций обновления.


Реактивность

Реактивная модель основана на присваиваниях. Любое изменение значения переменной автоматически инициирует обновление DOM.

Реактивные декларации задаются через метку $::

<script>
  let a = 2;
  let b = 3;

  $: sum = a + b;
</script>

<p>{sum}</p>

Зависимости вычисляются статически на этапе компиляции, что позволяет точно определять, какие части интерфейса требуют обновления.


Реактивные блоки

Реактивные блоки позволяют выполнять код при изменении зависимостей:

<script>
  let count = 0;

  $: {
    if (count > 10) {
      console.log("Порог превышен");
    }
  }
</script>

Блоки компилируются в условные обновления, привязанные к конкретным переменным.


Привязка данных (bind)

Механизм двусторонней привязки обеспечивает синхронизацию состояния и DOM-элементов.

<script>
  let text = "";
</script>

<input bind:value={text} />
<p>{text}</p>

Поддерживаются различные типы привязок:

  • bind:value
  • bind:checked
  • bind:group
  • bind:this

Компонентная модель

Компоненты представляют собой изолированные единицы с локальным состоянием и стилями.

Передача данных осуществляется через props:

<!-- Child.svelte -->
<script>
  export let name;
</script>

<h1>{name}</h1>
<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte';
</script>

<Child name="Interface" />

Изоляция стилей реализуется автоматически через добавление уникальных атрибутов к DOM-элементам.


События

Обработка событий использует директивы вида on:event.

<script>
  function handleClick() {
    alert("Нажатие");
  }
</script>

<button on:click={handleClick}>
  Кнопка
</button>

Поддерживается модификация поведения событий:

  • on:click|preventDefault
  • on:submit|stopPropagation

Stores и глобальное состояние

Для управления состоянием вне компонентов используется система stores.

Базовый writable store:

import { writable } from 'svelte/store';

export const counter = writable(0);

Использование внутри компонента:

<script>
  import { counter } from './store.js';
</script>

<button on:click={() => counter.update(n => n + 1)}>
  {$counter}
</button>

Подписка на store осуществляется автоматически при использовании префикса $.


Derived stores

Производные состояния вычисляются на основе других store:

import { derived } from 'svelte/store';
import { counter } from './store.js';

export const doubled = derived(counter, $counter => $counter * 2);

Жизненный цикл компонентов

Поддерживаются стандартные хуки жизненного цикла:

  • onMount
  • beforeUpdate
  • afterUpdate
  • onDestroy

Пример:

<script>
  import { onMount } from 'svelte';

  onMount(() => {
    console.log("Компонент инициализирован");
  });
</script>

Контекст

Механизм контекста позволяет передавать данные без явного прокидывания через props.

<script>
  import { setContext } from 'svelte';

  setContext('theme', 'dark');
</script>
<script>
  import { getContext } from 'svelte';

  const theme = getContext('theme');
</script>

Анимации и переходы

Встроенная система переходов обеспечивает декларативные анимации появления и исчезновения элементов.

<script>
  import { fade } from 'svelte/transition';
  let visible = true;
</script>

{#if visible}
  <div transition:fade>
    Контент
  </div>
{/if}

Поддерживаются:

  • fade
  • slide
  • fly
  • кастомные transition-функции

Модули и scoped styles

Стили внутри компонента ограничены областью видимости.

<style>
  h1 {
    color: red;
  }
</style>

Компилятор преобразует селекторы в уникальные комбинации атрибутов, исключая конфликты стилей.


SSR и гидратация

Фреймворк поддерживает серверный рендеринг с последующей гидратацией на клиенте. Это позволяет:

  • ускорить первую отрисовку;
  • улучшить SEO;
  • уменьшить нагрузку на клиентский JavaScript.

Гидратация связывает уже отрендеренный HTML с интерактивной логикой компонентов.


Экосистема и расширения

SvelteKit расширяет базовую модель, добавляя:

  • маршрутизацию;
  • серверные endpoints;
  • гибридный SSR/SPA режим;
  • интеграцию с адаптерами для различных платформ.

Структура проекта в SvelteKit обычно включает:

  • routes/ — страницы и маршруты
  • lib/ — переиспользуемые модули
  • hooks — серверные и клиентские хуки

Производительность

Оптимизация достигается за счёт:

  • отсутствия виртуального DOM;
  • статического анализа зависимостей;
  • минимального runtime;
  • точечных обновлений DOM.

Компилятор удаляет неиспользуемый код, сокращая размер бандла и ускоряя выполнение.


Типизация и интеграция с TypeScript

Поддержка TypeScript реализуется на уровне препроцессора.

<script lang="ts">
  let count: number = 0;
</script>

Типизация улучшает предсказуемость компонентов и снижает количество ошибок при масштабировании приложения.