Перейти к содержимому

2. Установка и Vite

Svelte — это компилятор, а не обычный фреймворк. Он преобразует твои компоненты в чистый, оптимизированный JavaScript во время сборки, без runtime-накладных расходов. Результат — молниеносные приложения с минимальным bundle size. 🚀

Сегодня разберём два способа создать Svelte-проект: через официальный SvelteKit (полный фарш — роутинг, SSR, API) и через чистый Vite + Svelte (простой SPA без лишнего). Разберёмся с каждым файлом проекта по очереди!


┌──────────────────────────────────────────────────────────────┐
│ Выбор подхода │
├────────────────────────────────┬─────────────────────────────┤
│ npm create svelte@latest │ npm create vite@latest │
│ (SvelteKit) │ (Pure Svelte + Vite) │
├────────────────────────────────┼─────────────────────────────┤
│ ✅ Файловый роутинг │ ✅ Минимальная настройка │
│ ✅ SSR / SSG из коробки │ ✅ Идеально для SPA │
│ ✅ API routes (+server.ts) │ ✅ Быстрый старт │
│ ✅ Адаптеры (Vercel, Netlify) │ ✅ Полный контроль │
│ ✅ Load functions │ ✅ Легко понять структуру │
│ ❌ Сложнее для первого знак. │ ❌ Нет роутинга │
│ ❌ Больше концепций сразу │ ❌ Нет SSR │
└────────────────────────────────┴─────────────────────────────┘

Правило Яши: начни с Vite-only, чтобы освоить Svelte без лишних концепций. Потом переходи на SvelteKit!


Способ 1: Vite + Svelte (рекомендую для старта) 🚀

Заголовок раздела «Способ 1: Vite + Svelte (рекомендую для старта) 🚀»
Окно терминала
npm create vite@latest my-svelte-app -- --template svelte-ts
# Переходим в папку
cd my-svelte-app
# Устанавливаем зависимости
npm install
# Запускаем dev-сервер
npm run dev

В терминале увидишь что-то вроде:

VITE v5.x.x ready in 300ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help

Открывай http://localhost:5173 — твой первый Svelte-проект уже работает! 🎉

Окно терминала
# Без TypeScript
npm create vite@latest my-app -- --template svelte
# С TypeScript (рекомендуется)
npm create vite@latest my-app -- --template svelte-ts
# Посмотреть все шаблоны
npm create vite@latest

Способ 2: SvelteKit (для полноценных приложений) 🏗️

Заголовок раздела «Способ 2: SvelteKit (для полноценных приложений) 🏗️»
Окно терминала
# Официальный создатор SvelteKit проектов
npm create svelte@latest my-sveltekit-app
# Мастер задаст несколько вопросов:
# ┌ Welcome to SvelteKit!
# │
# ◆ Which Svelte app template?
# │ ● SvelteKit demo app
# │ ○ Skeleton project ← выбери это для чистого старта
# │ ○ Library project
# │
# ◆ Add type checking with TypeScript?
# │ ○ Yes, using JavaScript with JSDoc comments
# │ ● Yes, using TypeScript syntax ← рекомендуется
# │ ○ No
# │
# ◆ Select additional options:
# │ ☑ Add ESLint for code linting
# │ ☑ Add Prettier for code formatting
# │ ☐ Add Playwright for browser testing
# │ ☐ Add Vitest for unit testing
cd my-sveltekit-app
npm install
npm run dev

my-svelte-app/
├── public/ # Статические файлы (копируются as-is)
│ └── vite.svg
├── src/
│ ├── lib/ # Переиспользуемые компоненты и утилиты
│ │ └── Counter.svelte # Пример компонента из шаблона
│ ├── assets/ # Картинки, шрифты (обрабатываются Vite)
│ │ └── svelte.svg
│ ├── App.svelte # Корневой компонент приложения
│ ├── app.css # Глобальные стили
│ └── main.ts # Точка входа — монтирует App в DOM
├── index.html # HTML-шаблон (Vite обрабатывает его)
├── vite.config.ts # Конфигурация Vite
├── svelte.config.js # Конфигурация компилятора Svelte
├── tsconfig.json # Конфигурация TypeScript
├── tsconfig.node.json # TypeScript для Node.js (vite.config.ts)
└── package.json
my-sveltekit-app/
├── src/
│ ├── lib/ # Импортируется как $lib/...
│ │ ├── components/
│ │ └── utils/
│ ├── routes/ # Файловый роутинг!
│ │ ├── +layout.svelte # Общий лэйаут для всех страниц
│ │ ├── +page.svelte # Страница /
│ │ ├── about/
│ │ │ └── +page.svelte # Страница /about
│ │ └── blog/
│ │ ├── +page.svelte # Страница /blog
│ │ ├── +page.server.ts # Load function (серверный код)
│ │ └── [slug]/
│ │ └── +page.svelte # Страница /blog/:slug
│ └── app.html # HTML-шаблон (с %sveltekit.head% и т.д.)
├── static/ # Статические файлы
├── svelte.config.js
└── package.json

Это самая важная часть! .svelte файл — это особый формат, который объединяет три секции в одном файле:

<!-- Секция 1: Логика компонента -->
<script lang="ts">
import { onMount } from 'svelte';
import ChildComponent from './ChildComponent.svelte';
// Props (в Svelte 5 — через $props())
let { title = 'Default Title', count = $bindable(0) } = $props();
// Локальное состояние (в Svelte 5 — $state())
let name = $state('World');
let items = $state<string[]>([]);
// Вычисляемые значения (в Svelte 5 — $derived())
let greeting = $derived(`Привет, ${name}!`);
// Эффекты (в Svelte 5 — $effect())
$effect(() => {
console.log('name изменился:', name);
});
// Обычные функции
function addItem(item: string): void {
items = [...items, item];
}
// Lifecycle
onMount(() => {
console.log('Компонент смонтирован');
});
</script>
<!-- Секция 2: Шаблон (HTML + Svelte синтаксис) -->
<!-- Нет обёртки вроде <template> или <div> — фрагменты поддерживаются! -->
<main class="container">
<h1>{greeting}</h1>
<p>Title: {title}</p>
{#each items as item, i (item)}
<div>{i + 1}. {item}</div>
{/each}
<ChildComponent bind:value={name} />
</main>
<!-- Секция 3: Стили (SCOPED по умолчанию!) -->
<style>
/* Эти стили применяются ТОЛЬКО к этому компоненту */
/* Svelte добавляет уникальный класс: .container.svelte-abc123 */
.container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
h1 {
color: #ff3e00; /* Svelte orange! */
}
/* :global() — если нужно глобально */
:global(body) {
margin: 0;
}
</style>

Секция <script context="module"> — запускается один раз

Заголовок раздела «Секция <script context="module"> — запускается один раз»
<!-- Запускается при ИМПОРТЕ модуля, не при создании компонента -->
<!-- Shared между всеми экземплярами компонента -->
<script context="module">
// Здесь можно экспортировать функции и переменные
export const componentVersion = '1.0.0';
// Загрузка данных до рендера (паттерн SvelteKit)
export async function load({ fetch }) {
const response = await fetch('/api/data');
return { data: await response.json() };
}
</script>
<script lang="ts">
// Обычный скрипт компонента
let count = $state(0);
</script>
ComponentA.svelte
<style>
p { color: red; } /* Применяется ТОЛЬКО к p внутри этого компонента */
</style>
<!-- Svelte компилирует это в: -->
<!-- p.svelte-x7k2p9 { color: red; } -->
<!-- И добавляет класс к элементу: <p class="svelte-x7k2p9"> -->

Никаких конфликтов стилей между компонентами! 🎯


import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [
svelte({
// Опции плагина (обычно берутся из svelte.config.js)
configFile: './svelte.config.js',
}),
],
// Сервер разработки
server: {
port: 5173, // Порт
open: true, // Открыть браузер автоматически
host: true, // Доступ из сети (0.0.0.0)
},
// Сборка для production
build: {
outDir: 'dist',
sourcemap: true, // Source maps для дебага
minify: 'terser', // Минификация
target: 'esnext', // Целевые браузеры
rollupOptions: {
output: {
// Разделение чанков
manualChunks: {
'vendor': ['svelte'],
},
},
},
},
// Псевдонимы путей
resolve: {
alias: {
'@': '/src',
'$lib': '/src/lib',
},
},
});

import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
export default {
// Препроцессоры — обработка <style lang="scss">, <script lang="ts"> и т.д.
preprocess: vitePreprocess(),
// Настройки компилятора Svelte
compilerOptions: {
// Включить новый режим Svelte 5 (рекомендуется!)
runes: true,
// Предупреждения (a11y и другие)
warningFilter: (warning) => {
// Отключить конкретные предупреждения
if (warning.code === 'a11y-missing-attribute') return false;
return true;
},
},
// Для SvelteKit — настройка Kit
// kit: {
// adapter: adapter(),
// },
};
Окно терминала
# Sass/SCSS стили
npm install -D sass
# В компоненте:
# <style lang="scss">
# .container {
# &__title { color: #ff3e00; }
# }
# </style>
// svelte.config.js с несколькими препроцессорами
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import { preprocessMeltUI } from '@melt-ui/pp';
import sequence from 'svelte-sequential-preprocessor';
export default {
preprocess: sequence([
vitePreprocess(),
preprocessMeltUI(), // MeltUI компоненты
]),
};

TypeScript включён из коробки в шаблоне svelte-ts. Вот что важно знать:

// tsconfig.json — стандартная конфигурация
{
"extends": "./.svelte-kit/tsconfig.json", // SvelteKit
// или для Vite:
"compilerOptions": {
"target": "ES2022",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.svelte"]
}
<script lang="ts">
// Svelte 5: типизация через интерфейс
interface Props {
name: string;
age?: number;
onUpdate?: (value: string) => void;
}
let { name, age = 18, onUpdate }: Props = $props();
</script>
<script lang="ts">
// Типизация кастомных событий (Svelte 4 стиль)
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher<{
submit: { value: string; timestamp: number };
cancel: void;
}>();
// Svelte 5 стиль — через props-функции
let { onsubmit }: { onsubmit: (data: { value: string }) => void } = $props();
</script>

1. Svelte for VS Code (svelte.svelte-vscode) — ОБЯЗАТЕЛЬНО!
- Syntax highlighting
- IntelliSense и автодополнение
- Форматирование кода
- Диагностика ошибок TypeScript
2. Prettier - Code formatter (esbenp.prettier-vscode)
3. ESLint (dbaeumer.vscode-eslint)
{
// Форматировать .svelte файлы через Prettier
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode",
"editor.formatOnSave": true
},
// TypeScript — использовать workspace версию
"typescript.tsdk": "node_modules/typescript/lib",
// Включить проверку типов в .svelte файлах
"svelte.enable-ts-plugin": true,
// Автоимпорт компонентов
"svelte.plugin.svelte.compilerWarnings": {
"a11y-missing-attribute": "ignore",
"a11y-missing-content": "ignore"
}
}
{
"useTabs": false,
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [
{
"files": "*.svelte",
"options": { "parser": "svelte" }
}
]
}

Окно терминала
# Dev-сервер с HMR (Hot Module Replacement)
npm run dev
# Dev-сервер доступный в локальной сети
npm run dev -- --host
# Сборка для production
npm run build
# Превью production-сборки локально
npm run preview
# Проверка TypeScript без компиляции
npx tsc --noEmit
# Линтинг
npm run lint
# Форматирование
npm run format
src/
App.svelte ──→ (Svelte компилятор) ──→ App.js (чистый JS!)
main.ts ──→ (TypeScript) ──→ main.js
(Vite Rollup)
dist/
index.html (с инжектированными скриптами)
assets/
index-Abc123.js (bundle, минифицирован)
index-Xyz789.css (стили)

Svelte компилирует компоненты — в итоговом bundle нет Svelte runtime! Только твой код + маленький helpers файл (~8kb).


Давай создадим полноценный компонент с состоянием, событиями и стилями:

src/App.svelte
<script lang="ts">
// Svelte 5: реактивное состояние через rune $state
let name = $state('Яша');
let count = $state(0);
let items = $state<string[]>(['Svelte', 'Vite', 'TypeScript']);
// Вычисляемое значение через $derived
let doubled = $derived(count * 2);
let greeting = $derived(`Привет, ${name}! 👋`);
// Функции обновления состояния
function increment(): void {
count++;
}
function addItem(): void {
const item = prompt('Добавить элемент:');
if (item) items = [...items, item];
}
function removeItem(index: number): void {
items = items.filter((_, i) => i !== index);
}
</script>
<!-- Шаблон — никаких обёрток не нужно! -->
<main>
<h1>{greeting}</h1>
<section class="counter">
<p>Счётчик: <strong>{count}</strong> (×2 = {doubled})</p>
<div class="buttons">
<button onclick={() => count--}>−</button>
<button onclick={increment}>+</button>
<button onclick={() => count = 0} class="reset">сброс</button>
</div>
</section>
<section class="list">
<h2>Стек технологий:</h2>
{#each items as item, i (item)}
<div class="item">
<span>{i + 1}. {item}</span>
<button onclick={() => removeItem(i)}>✕</button>
</div>
{/each}
<button onclick={addItem} class="add">+ Добавить</button>
</section>
</main>
<style>
main {
max-width: 500px;
margin: 2rem auto;
padding: 1rem;
font-family: system-ui, sans-serif;
}
h1 {
color: #ff3e00;
font-size: 2rem;
}
.counter {
background: #f8f8f8;
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
}
.buttons {
display: flex;
gap: 8px;
}
button {
padding: 0.5rem 1rem;
border: none;
border-radius: 6px;
cursor: pointer;
background: #ff3e00;
color: white;
font-size: 1rem;
}
button.reset {
background: #666;
}
button.add {
margin-top: 0.5rem;
background: #40b3ff;
}
.item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem;
border-bottom: 1px solid #eee;
}
.item button {
background: transparent;
color: #ff3e00;
padding: 0.2rem 0.5rem;
font-size: 0.8rem;
}
</style>
// src/main.ts — точка входа
import { mount } from 'svelte';
import './app.css';
import App from './App.svelte';
const app = mount(App, {
target: document.getElementById('app')!,
props: {
// Если нужно передать начальные props
}
});
export default app;

Что мы узнали:

  • Vite + Svelte — для SPA, быстрый старт
  • SvelteKit — для SSR/SSG, файловый роутинг, полноценные приложения
  • .svelte файл — три секции: <script>, шаблон, <style>
  • Scoped стили — по умолчанию, без конфликтов
  • TypeScript — через <script lang="ts">
  • vite.config.ts — сборщик, плагины, dev-сервер
  • svelte.config.js — компилятор, препроцессоры

Следующий шаг — базовый синтаксис: интерполяция, директивы классов и стилей! 📝