ESLint в проектах на Svelte

Интеграция ESLint в проекты на Svelte строится вокруг необходимости анализировать не только JavaScript/TypeScript-код, но и шаблонную часть .svelte файлов. В отличие от классических SPA-фреймворков, Svelte компилирует компоненты на этапе сборки, что создаёт дополнительный слой синтаксиса, требующий специализированного парсера и плагинов.

ESLint по умолчанию работает только с ECMAScript-кодом. Svelte-компоненты же содержат три логических блока:

  • <script> (JS/TS логика)
  • <style> (CSS)
  • markup (шаблон)

Именно markup является ключевой проблемой для стандартного ESLint-пайплайна, так как он не является валидным JavaScript.

Парсинг Svelte-файлов

Для анализа .svelte файлов используется специализированный парсер svelte-eslint-parser. Он преобразует Svelte-компонент в AST-структуру, совместимую с ESLint.

Внутренняя модель работы выглядит следующим образом:

  1. Svelte-файл разбивается на блоки (script, style, template)
  2. <script> парсится стандартным JS/TS парсером (например, espree или @typescript-eslint/parser)
  3. template преобразуется в расширенный AST с HTML-узлами
  4. результат объединяется в единое дерево для ESLint-анализа

Ключевая особенность — AST содержит гибридные узлы, такие как:

  • SvelteMustacheTag
  • SvelteAttribute
  • SvelteDirective
  • SvelteFragment

Эти узлы позволяют писать правила, ориентированные на шаблонную логику.

Базовая конфигурация ESLint для Svelte

Стандартная настройка начинается с установки пакетов:

npm install -D eslint svelte-eslint-parser eslint-plugin-svelte

Основная конфигурация:

export default {
  files: ["**/*.svelte"],
  languageOptions: {
    parser: "svelte-eslint-parser",
    parserOptions: {
      parser: "@typescript-eslint/parser",
      extraFileExtensions: [".svelte"],
      ecmaVersion: "latest",
      sourceType: "module"
    }
  },
  plugins: {
    svelte: eslintPluginSvelte
  },
  rules: {
    "svelte/no-unused-svelte-ignore": "warn"
  }
};

Роль eslint-plugin-svelte

Плагин eslint-plugin-svelte является центральным элементом экосистемы линтинга Svelte. Он содержит набор правил, ориентированных на:

  • корректность реактивных выражений
  • использование $: реактивных деклараций
  • обработку событий (on:click, on:input)
  • оптимизацию шаблонов
  • предотвращение логических ошибок в компонентной модели

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

Одной из ключевых особенностей Svelte является реактивность через метки $:. ESLint может контролировать корректность зависимостей.

Пример проблемного кода:

<script>
  let a = 1;
  let b = 2;
  let sum;

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

Расширенные правила могут проверять:

  • наличие неиспользуемых реактивных переменных
  • корректность зависимостей реактивного выражения
  • предотвращение лишних вычислений

Интеграция TypeScript в Svelte ESLint

При использовании TypeScript в Svelte добавляется дополнительный слой сложности. Конфигурация расширяется через @typescript-eslint/parser.

parserOptions: {
  parser: "@typescript-eslint/parser",
  project: "./tsconfig.json",
  extraFileExtensions: [".svelte"]
}

Это позволяет:

  • анализировать типы внутри <script lang="ts">
  • находить несоответствия типов в props
  • проверять события компонентов
  • интегрировать строгую типизацию с шаблонной частью

Правила для шаблонного слоя

Template-часть Svelte имеет собственные особенности, которые требуют отдельных правил ESLint.

Атрибуты и биндинги

<input bind:value={name} />

Линтер может проверять:

  • существование переменной name
  • корректность bind-выражений
  • отсутствие недопустимых биндингов (например, к read-only значениям)

Директивы

Svelte использует директивы:

  • on:click
  • bind:
  • use:
  • transition:

ESLint-правила могут анализировать:

  • правильность названий обработчиков
  • отсутствие inline-сложной логики
  • корректность пользовательских actions

Работа с событиями

Событийная модель Svelte отличается от DOM напрямую. ESLint помогает контролировать:

<button on:click={handleClick}>OK</button>

Проверки включают:

  • существование handleClick
  • отсутствие небезопасных inline-функций
  • соблюдение naming conventions

Расширенные правила могут запрещать:

<button on:click={() => console.log('test')}>OK</button>

Управление состоянием и реактивностью

Svelte не использует классический virtual DOM, поэтому ESLint-правила фокусируются на реактивных присваиваниях.

$: doubled = count * 2;

Типовые проверки:

  • использование неинициализированных переменных
  • циклические реактивные зависимости
  • избыточные пересчёты

Настройка игнорирования и исключений

ESLint в Svelte-проектах часто требует тонкой настройки исключений:

rules: {
  "svelte/no-unused-svelte-ignore": "error",
  "svelte/valid-compile": "error"
}

В Svelte допускается использование комментариев:

<!-- eslint-disable-next-line -->
<div>{anyEx * pression()}</div>

Плагин обеспечивает контроль за корректностью таких отключений, предотвращая скрытие ошибок.

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

Некоторые правила направлены не на синтаксис, а на производительность:

  • предотвращение тяжёлых вычислений в шаблоне
  • контроль повторных подписок
  • избегание создания функций в разметке

Пример анти-паттерна:

{#each items as item}
  <div>{expensiveCalculation(item)}</div>
{/each}

Линтер может рекомендовать вынесение вычислений в реактивные блоки.

Интеграция с форматированием кода

ESLint в Svelte-проектах часто комбинируется с форматерами. Основная цель — разделение ответственности:

  • ESLint: логика, корректность, архитектура
  • форматер: стиль и внешний вид

При конфликте правил отключаются stylistic rules ESLint, чтобы избежать дублирования функций форматирования.

Монорепозитории и масштабирование

В крупных проектах Svelte ESLint конфигурация часто становится частью монорепозитория:

  • отдельные конфиги для UI-библиотек
  • базовые правила для приложений
  • расширения для серверного кода (Node.js)

Используются shared-config подходы:

export default [
  baseConfig,
  svelteConfig,
  tsConfig
];

Инкрементальный линтинг

В больших Svelte-проектах ESLint используется в режиме:

  • кеширования результатов
  • анализа изменённых файлов
  • параллельной обработки компонентов

Это особенно важно, так как Svelte-компоненты требуют двойного разбора (template + script).

Типичные ошибки конфигурации

Распространённые проблемы:

  • отсутствие extraFileExtensions: [".svelte"]
  • неправильный parser chain (TS не подключён к svelte parser)
  • конфликт eslint-plugin-svelte и eslint-plugin-svelte3
  • отсутствие поддержки ESM-конфигураций
  • попытка использовать обычный eslint:recommended без адаптации под Svelte

Современные практики организации правил

В зрелых проектах правила группируются:

  • базовые правила качества кода
  • правила Svelte-шаблонов
  • правила TypeScript
  • правила производительности
  • правила архитектуры компонентов

Такой подход позволяет поддерживать предсказуемость поведения линтера при росте проекта и усложнении компонентной структуры.