10. Svelte в Astro
Svelte — компилятор-фреймворк с минимальным runtime. В отличие от React и Vue, Svelte компилирует компоненты в чистый ванильный JavaScript во время сборки, что даёт значительно меньший размер бандла — идеально для Astro Islands.
Установка интеграции
Заголовок раздела «Установка интеграции»npx astro add svelteКоманда автоматически:
- Устанавливает
@astrojs/svelteиsvelte - Обновляет
astro.config.mjs - Настраивает компилятор Svelte
Конфигурация astro.config.mjs
Заголовок раздела «Конфигурация astro.config.mjs»import { defineConfig } from 'astro/config';import svelte from '@astrojs/svelte';
export default defineConfig({ integrations: [svelte()],});Svelte компонент в Astro
Заголовок раздела «Svelte компонент в Astro»<script> export let initialCount = 0; let count = initialCount;</script>
<div class="counter"> <button on:click={() => count--}>−</button> <span>{count}</span> <button on:click={() => count++}>+</button></div>
<style> .counter { display: flex; align-items: center; gap: 12px; } span { font-size: 1.5rem; font-weight: bold; }</style>---import SvelteCounter from '../components/SvelteCounter.svelte';---
<SvelteCounter initialCount={10} client:load />Svelte stores с Astro
Заголовок раздела «Svelte stores с Astro»Svelte stores работают как глобальное состояние и могут использоваться для коммуникации между Islands:
import { writable, derived } from 'svelte/store';
export const cartItems = writable([]);
export const cartTotal = derived(cartItems, ($items) => $items.reduce((sum, item) => sum + item.price * item.qty, 0));
export const addToCart = (product) => { cartItems.update(items => { const existing = items.find(i => i.id === product.id); if (existing) { return items.map(i => i.id === product.id ? { ...i, qty: i.qty + 1 } : i); } return [...items, { ...product, qty: 1 }]; });};<script> import { cartItems } from '../store/cart.js';</script>
<button> 🛒 {$cartItems.length}</button>Svelte анимации в Astro Islands
Заголовок раздела «Svelte анимации в Astro Islands»Svelte предлагает встроенные анимации без дополнительных зависимостей:
<script> import { fly, fade, scale } from 'svelte/transition'; import { flip } from 'svelte/animate';
let items = ['Astro', 'Svelte', 'Islands']; let newItem = '';
const add = () => { if (newItem.trim()) { items = [...items, newItem.trim()]; newItem = ''; } };
const remove = (i) => { items = items.filter((_, index) => index !== i); };</script>
<div> <div class="input-row"> <input bind:value={newItem} on:keydown={(e) => e.key === 'Enter' && add()} /> <button on:click={add}>Добавить</button> </div>
<ul> {#each items as item, i (item)} <li animate:flip={{ duration: 300 }} transition:fly={{ y: -20, duration: 300 }}> {item} <button on:click={() => remove(i)}>×</button> </li> {/each} </ul></div>Преимущество компилятора: размер бандла
Заголовок раздела «Преимущество компилятора: размер бандла»Svelte компилирует компоненты в ванильный JS без необходимости загружать runtime библиотеку:
| Фреймворк | Runtime | Типичный компонент |
|---|---|---|
| React | ~45kb | +1-5kb |
| Vue | ~34kb | +2-8kb |
| Svelte | ~1.5kb | +1-3kb |
<!-- Svelte компилирует это... --><script> let count = 0;</script><button on:click={() => count++}>{count}</button>
<!-- ...в чистый JS (~300 байт): --><!-- function create_fragment(ctx) { ... } -->Svelte с TypeScript в Astro
Заголовок раздела «Svelte с TypeScript в Astro»<script lang="ts"> export let initialCount: number = 0; export let step: number = 1; export let label: string = 'Счётчик';
let count: number = initialCount;
const increment = (): void => { count += step; }; const decrement = (): void => { count -= step; }; const reset = (): void => { count = initialCount; };</script>
<div> <h3>{label}: {count}</h3> <button on:click={decrement}>−{step}</button> <button on:click={reset}>Сброс</button> <button on:click={increment}>+{step}</button></div>