ESLint и Rollup

В экосистеме современного JavaScript сборщик Rollup и статический анализатор кода ESLint решают разные, но взаимодополняющие задачи. Rollup отвечает за упаковку модулей в оптимизированные бандлы, а ESLint обеспечивает контроль качества исходного кода до этапа сборки. Их совместная работа формирует многоуровневую систему проверки, где ошибки выявляются как на уровне синтаксиса и стиля, так и на уровне архитектурных соглашений.

ESLint интегрируется в пайплайн Rollup не как часть трансформации кода, а как промежуточный шаг анализа. Это позволяет предотвращать попадание проблемного кода в процесс бандлинга, снижая вероятность появления дефектов в продакшн-сборке.


Базовые модели интеграции ESLint и Rollup

Существует несколько подходов к использованию ESLint вместе с Rollup:

  1. Запуск ESLint до сборки (pre-build)
  2. Использование ESLint как Rollup-плагина
  3. Разделение процессов lint и build в CI/CD
  4. Интеграция через watcher в режиме разработки

Каждая модель выбирается в зависимости от масштаба проекта, требований к скорости сборки и глубины проверки кода.


Использование ESLint перед запуском Rollup

Наиболее предсказуемая архитектура — запуск ESLint как отдельного этапа до Rollup. Такой подход исключает попадание некорректного кода в систему сборки.

Пример скриптов:

{
  "scripts": {
    "lint": "eslint src",
    "build": "npm run lint && rollup -c"
  }
}

В этом случае Rollup не запускается, пока ESLint не завершится без ошибок. Это обеспечивает строгую дисциплину качества кода, особенно в проектах с несколькими разработчиками.


ESLint как плагин Rollup

Для более тесной интеграции используется плагинный механизм Rollup. Один из распространённых вариантов — @rollup/plugin-eslint.

Установка:

npm install -D @rollup/plugin-eslint eslint

Пример конфигурации Rollup:

import eslint from '@rollup/plugin-eslint';

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'esm'
  },
  plugins: [
    eslint({
      include: ['src/**/*.js'],
      exclude: ['node_modules/**'],
      throwOnError: true,
      throwOnWarning: false
    })
  ]
};

Такой подход позволяет анализировать код прямо в процессе построения графа модулей Rollup. Ошибки ESLint могут прерывать сборку, а предупреждения — лишь фиксироваться в консоли.


Встраивание ESLint в граф модулей Rollup

Rollup строит граф зависимостей, начиная с entry-point и рекурсивно проходя по импортам. ESLint-плагин подключается на этапе загрузки модулей и анализирует содержимое каждого файла до его включения в бандл.

Важный аспект — порядок выполнения плагинов. ESLint обычно размещается до трансформационных плагинов (Babel, TypeScript), чтобы анализировать исходный код, а не уже транспилированный результат.

Пример:

import eslint from '@rollup/plugin-eslint';
import typescript from '@rollup/plugin-typescript';

export default {
  input: 'src/index.ts',
  plugins: [
    eslint({
      include: ['src/**/*.{ts,js}']
    }),
    typescript()
  ]
};

ESLint и TypeScript в Rollup-пайплайне

При использовании TypeScript возникает вопрос: анализировать исходный .ts или уже преобразованный код.

Оптимальная схема:

  • ESLint с @typescript-eslint/parser анализирует TypeScript до компиляции
  • Rollup через @rollup/plugin-typescript выполняет транспиляцию

Конфигурация ESLint:

export default {
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended'
  ]
};

Rollup:

import typescript from '@rollup/plugin-typescript';
import eslint from '@rollup/plugin-eslint';

export default {
  input: 'src/main.ts',
  plugins: [
    eslint({
      include: ['src/**/*.ts']
    }),
    typescript()
  ]
};

Производительность ESLint в Rollup

ESLint может стать узким местом при большом количестве модулей. При интеграции в Rollup важно учитывать:

  • количество файлов в графе зависимостей
  • сложность правил ESLint
  • частоту пересборок в watch-режиме

Для оптимизации применяются следующие стратегии:

1. Ограничение области анализа

eslint({
  include: ['src/core/**']
})

2. Кэширование результатов линтинга

Некоторые конфигурации ESLint поддерживают кэш:

eslint src --cache

3. Разделение lint и build

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


Watch-режим Rollup и ESLint

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

Rollup watch:

export default {
  watch: {
    include: 'src/**'
  }
};

При интеграции ESLint важно избегать повторного анализа всего проекта при каждом изменении одного файла. Для этого используются стратегии:

  • lint только изменённого файла
  • использование внешних watcher-утилит
  • запуск ESLint вне Rollup watcher

Monorepo-архитектура

В монорепозиториях ESLint и Rollup часто применяются на уровне пакетов. Структура:

packages/
  ui/
  core/
  utils/

Rollup собирает каждый пакет отдельно, а ESLint работает либо глобально, либо на уровне пакета.

Пример глобального lint:

eslint "packages/**/src"

Rollup-конфигурации при этом изолированы, но используют единый набор правил ESLint через shared config:

module.exports = {
  extends: ['../. ./eslint.base.js']
};

Flat Config ESLint и Rollup

Современный формат ESLint Flat Config упрощает интеграцию в сборочные системы.

Пример:

export default [
  {
    files: ['src/**/*.js'],
    rules: {
      semi: ['error', 'always']
    }
  }
];

В связке с Rollup это снижает накладные расходы на парсинг конфигурации и ускоряет старт сборки.


Ошибки линтинга и поведение Rollup

Поведение сборки при ошибках ESLint определяется настройками плагина:

  • throwOnError: true — остановка сборки
  • throwOnError: false — продолжение сборки с выводом ошибок

Строгий режим:

eslint({
  throwOnError: true
})

Мягкий режим:

eslint({
  throwOnError: false,
  throwOnWarning: false
})

В производственных сборках обычно применяется строгий режим, тогда как в разработке допускается более мягкая политика.


Разделение ответственности между ESLint и Rollup

ESLint выполняет статический анализ:

  • обнаружение неиспользуемых переменных
  • контроль импортов
  • проверка синтаксических паттернов
  • соблюдение архитектурных правил

Rollup выполняет:

  • объединение модулей
  • tree-shaking
  • генерацию финального бандла
  • оптимизацию экспорта

Пересечение зон ответственности отсутствует, что делает их комбинацию устойчивой к усложнению проекта.


ESLint в многоступенчатых сборках Rollup

В сложных пайплайнах Rollup может включать несколько стадий:

  1. ESLint
  2. TypeScript трансформация
  3. Babel трансформация
  4. минификация
  5. постобработка

Пример цепочки:

plugins: [
  eslint(),
  typescript(),
  babel({ babelHelpers: 'bundled' })
]

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


Ошибки конфигурации и типичные проблемы

Частые проблемы интеграции:

  • анализ уже транспилированного кода вместо исходников
  • дублирование lint-проверок (ESLint + TypeScript checker)
  • конфликт правил между базовыми конфигурациями
  • чрезмерно широкие include-паттерны
  • блокировка watch-сборки из-за строгого режима

Каждая из этих проблем приводит к замедлению или нестабильности сборочного процесса.


ESLint, Rollup и архитектура качества кода

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