Svelte / SvelteKitSeniorExperience

Проект на Svelte / SvelteKit вырос из небольшого интерфейса в большой продукт. Какие архитектурные проблемы вы ожидаете увидеть?

При росте проекта типичные проблемы: утечка глобальных stores в SSR, плоская структура маршрутов без group layouts, отсутствие типизированного API-слоя и дублирование логики авторизации в каждом load().

Архитектурные проблемы при масштабировании Svelte / SvelteKit

Когда проект вырастает из MVP, накапливаются архитектурные долги, специфичные для Svelte/SvelteKit.

Состояние приложения

В маленьких проектах используют глобальные writable()-хранилища в src/lib/stores.ts. При росте:

  • Хранилища становятся тесно связанными — изменение одного требует обновления десятков подписчиков.
  • В SSR глобальные хранилища создаются один раз и могут утекать данные между запросами разных пользователей.
  • Решение: переход на Svelte 5 Runes с $state, $derived и контекстную передачу состояния через setContext/getContext.
// src/lib/context/user.ts — безопасный контекст вместо глобального store
import { setContext, getContext } from 'svelte';
import { writable } from 'svelte/store';

const USER_KEY = Symbol('user');

export function initUserContext(initialUser: User | null) {
  const store = writable(initialUser);
  setContext(USER_KEY, store);
  return store;
}

export function getUserContext() {
  return getContext<ReturnType<typeof writable<User | null>>>(USER_KEY);
}

Структура маршрутов

  • Плоская структура src/routes/ становится неудобной при 50+ страницах.
  • Отсутствие чёткого разделения на +page.server.ts (данные) и +page.svelte (отображение) приводит к смешению логики.
  • Grouped routes (marketing)/, (app)/ позволяют использовать разные layouts без влияния на URL.

Переиспользование компонентов и дизайн-система

  • Без договорённостей компоненты дублируются в разных частях приложения.
  • Нет стандартного способа документирования — нужна интеграция с Histoire или Storybook (через @storybook/svelte).

Типизация данных

  • SvelteKit генерирует типы для параметров маршрутов в .svelte-kit/types/, но их нужно явно импортировать.
  • При отсутствии строгой типизации load() функций ошибки проявляются только в runtime.
// +page.server.ts — правильная типизация через PageServerLoad
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params, locals }) => {
  const user = locals.user; // типизировано через app.d.ts
  return { user };
};

API слой

  • API-эндпоинты в src/routes/api/ смешиваются с страницами — трудно тестировать изолированно.
  • Нет единого места для HTTP-клиента — каждый компонент делает fetch по-своему.
  • Решение: выделить src/lib/api/ с типизированными клиентами, использовать tRPC или zodios.

Производительность при большом числе компонентов

  • Svelte не имеет виртуального DOM, но при большом числе реактивных зависимостей граф реактивности растёт.
  • Компиляция svelte-check замедляется при 500+ компонентах без incremental builds.

Подводные камни

  • Глобальные writable() хранилища утекают между SSR-запросами — использовать только через setContext в корневом layout.
  • Групповые layouts (group)/+layout.svelte не наследуются автоматически — каждая вложенная группа нуждается в явном +layout.ts.
  • Миграция с Svelte 4 stores на Svelte 5 Runes требует переписывания всех реактивных зависимостей — нет автоматического кодмода.
  • Vite HMR при большом числе файлов начинает тормозить без optimizeDeps.include в vite.config.ts.
  • SvelteKit не поддерживает изоморфные middleware — логику авторизации нужно дублировать в каждом load() или централизовать через хук handle.
  • Параметры маршрутов ([id]) всегда строки — типовые ошибки при передаче числа скрыты без строгой типизации PageParams.
  • Storybook для Svelte значительно отстаёт по функциональности от React-версии — рассмотрите Histoire как альтернативу.
  • Отсутствие встроенного DI-контейнера затрудняет тестирование сервисного слоя — используйте паттерн factory functions с явными зависимостями.

What hurts your answer

  • Говорить только о запуске Svelte / SvelteKit, но не об эксплуатации
  • Не упоминать observability, обновления, безопасность и rollback
  • Описывать риски абстрактно, без способов их снижать

What they're listening for

  • Видит production-риски Svelte / SvelteKit
  • Говорит про monitoring, rollout, rollback и безопасность
  • Умеет ранжировать риски по вероятности и влиянию

Related topics