Чем Svelte отличается от React и Vue? Что означает «фреймворк времени компиляции» (compile-time framework)?
Svelte — компилятор: он преобразует компонент в нативный DOM-код на этапе сборки, без runtime VDOM. React и Vue несут движок реактивности в браузер, Svelte — нет, что даёт меньший бандл и более прямые обновления DOM.
Фреймворк времени компиляции: суть идеи
React и Vue — это runtime-фреймворки: в браузер поставляется движок (Virtual DOM или реактивная система), который во время работы страницы отслеживает изменения состояния, сравнивает деревья и обновляет DOM. Svelte работает принципиально иначе — компилятор анализирует .svelte-файлы на этапе сборки и генерирует нативный JavaScript, который напрямую вызывает DOM API (element.textContent = ..., element.setAttribute(...)) без каких-либо промежуточных абстракций в рантайме.
Конкретные отличия
- Размер бандла: приложение на Svelte не несёт в себе библиотеку (~40 КБ для React, ~22 КБ для Vue 3 core). Итоговый JS — только сгенерированный код.
- Реактивность: в React обновление инициируется вызовом
setState, в Vue — через Proxy. В Svelte компилятор помечает каждое присваивание (count = count + 1) и вставляет вызовы$$invalidate, которые точечно обновляют DOM без diffing. - Синтаксис: Svelte использует расширенный HTML с
{#if},{#each},{#await}, логика пишется прямо в теле компонента без JSX и без необходимости импортировать фреймворк в каждый файл. - Scoped CSS: стили внутри
<style>автоматически изолируются компилятором — не нужны CSS Modules или styled-components.
Как это выглядит на практике
// Counter.svelte — исходник
<script>
let count = 0;
function increment() { count += 1; }
</script>
<button on:click={increment}>{count}</button>
Компилятор превращает это примерно в:
// упрощённый псевдо-вывод компилятора
function create_fragment(ctx) {
let button;
return {
c() {
button = element('button');
button.textContent = ctx[0]; // count
},
m(target, anchor) {
insert(target, button, anchor);
listen(button, 'click', ctx[1]); // increment
},
p(ctx, [dirty]) {
if (dirty & 1) button.textContent = ctx[0]; // точечное обновление
},
d(detaching) {
if (detaching) detach(button);
}
};
}
SvelteKit
SvelteKit — это полноценный мета-фреймворк поверх Svelte (аналог Next.js для React). Он добавляет файловую маршрутизацию (src/routes/), серверные load-функции, SSR/SSG/SPA-режимы и адаптеры для развёртывания на Node, Cloudflare Workers, Vercel и т.д.
// src/routes/blog/[slug]/+page.server.js
export async function load({ params }) {
const post = await db.getPost(params.slug);
if (!post) throw error(404);
return { post };
}
Подводные камни
- Реактивность Svelte работает только для присваиваний — мутация массива через
arr.push()не вызовет обновление DOM без последующегоarr = arr. - Компилятор не отслеживает изменения вложенных объектов автоматически —
obj.x = 1не обновит компонент, еслиobjне переприсвоен. - TypeScript в
.svelte-файлах требуетlang="ts"на теге<script>и корректной настройки Vite/SvelteKit. - Экосистема существенно меньше, чем у React: меньше готовых UI-библиотек корпоративного уровня.
- Отладка скомпилированного кода сложнее — source maps помогают, но стековые трейсы иногда ведут в сгенерированный JS.
- Svelte 5 вводит новую систему реактивности на основе «рун» (
$state,$derived,$effect), ломающую обратную совместимость с кодом, написанным под Svelte 4. - При server-side rendering через SvelteKit некоторые браузерные API (
window,document) недоступны — нужна проверкаbrowserиз$app/environment.
Common mistakes
- Путать compile-time framework с похожим API из соседнего фреймворка.
- Не объяснять, где код выполняется: сервер, клиент, build step или runtime.
- Игнорировать влияние на hydration, cache, bundle size или безопасность.
What the interviewer is testing
- Точно объясняет назначение механизма «compile-time framework».
- Показывает корректный минимальный пример без выдуманных API.
- Называет ограничения, failure modes и production-компромиссы.