Как создавать и использовать плагины в Vite
  Создание пользовательских плагинов Vite позволяет расширить процесс сборки за пределы стандартной конфигурации — будь то преобразование пользовательских типов файлов, внедрение логики во время сборки или добавление middleware для сервера разработки. Если вы достигли пределов стандартной конфигурации Vite, создание собственного плагина — естественный следующий шаг.
Это руководство охватывает основные концепции: как работает Plugin API Vite, ключевые хуки жизненного цикла, которые вы будете использовать, и практические примеры для начала работы. Вы научитесь создавать, тестировать и публиковать плагины, которые решают реальные задачи в вашем рабочем процессе разработки.
Ключевые выводы
- Плагины Vite расширяют процессы разработки и production-сборки через хуки жизненного цикла
 - Большинство плагинов Rollup работают в Vite, но функции dev-сервера требуют специфичных для Vite хуков
 - Начните с простых преобразований, прежде чем переходить к продвинутым паттернам, таким как виртуальные модули
 - Следуйте соглашениям об именовании и стандартам документации при публикации плагинов
 
Понимание плагинов Vite и их связи с Rollup
Плагины Vite — это JavaScript-объекты, которые подключаются к различным этапам процесса разработки и сборки. Они построены на основе системы плагинов Rollup с дополнительными хуками, специфичными для сервера разработки Vite.
Vite использует два разных инструмента сборки под капотом: esbuild обеспечивает молниеносно быстрый сервер разработки с нативными ES-модулями, в то время как Rollup обрабатывает production-бандлинг для оптимального вывода. Эта двойная архитектура означает, что ваши плагины могут нацеливаться на конкретные окружения с помощью опции apply:
function myPlugin(): Plugin {
  return {
    name: 'my-plugin',
    apply: 'serve', // Only runs during development
    // ... hooks
  }
}
Большинство плагинов Rollup работают в Vite без модификаций. Однако, если вам нужна функциональность dev-сервера — например, добавление middleware или изменение HTML во время разработки — вам потребуются специфичные для Vite хуки.
Базовая структура плагина и конфигурация
Каждый плагин Vite должен иметь свойство name и как минимум одну функцию-хук:
import type { Plugin } from 'vite'
function myPlugin(options?: MyPluginOptions): Plugin {
  return {
    name: 'vite-plugin-example',
    enforce: 'pre', // Optional: control plugin ordering
    apply: 'build', // Optional: 'serve' | 'build' | undefined
    
    // Hook functions go here
    transform(code, id) {
      if (id.endsWith('.custom')) {
        return transformCustomFile(code)
      }
    }
  }
}
Plugin API предоставляет TypeScript-определения для всех хуков и опций. Импортируйте тип Plugin из ‘vite’ для полной типобезопасности и автодополнения.
Основные хуки жизненного цикла в Plugin API
Различные хуки срабатывают на разных этапах процесса сборки. Вот наиболее часто используемые:
Хуки конфигурации
config: Изменение конфигурации Vite до её разрешенияconfigResolved: Доступ к финальной разрешённой конфигурации
Хуки преобразования
transform: Изменение исходного кода отдельных модулейload: Пользовательская логика загрузки для конкретных типов файловresolveId: Пользовательское разрешение модулей
{
  name: 'transform-plugin',
  transform(code, id) {
    if (!id.includes('node_modules') && id.endsWith('.js')) {
      return {
        code: addCustomHeader(code),
        map: null // Source map support
      }
    }
  }
}
Хуки сервера и сборки
configureServer: Добавление пользовательского middleware к dev-серверуtransformIndexHtml: Изменение HTML-файловwriteBundle: Выполнение после записи бандла на диск
Каждый хук имеет специфичные типы возвращаемых значений и время выполнения. Хук transform запускается для каждого модуля, поэтому держите его быстрым. Используйте load для затратных операций над конкретными файлами.
Discover how at OpenReplay.com.
Создание вашего первого плагина Vite: практические примеры
Давайте создадим три практических плагина, демонстрирующих распространённые паттерны:
Пример 1: Модификация HTML
function htmlPlugin(): Plugin {
  return {
    name: 'html-modifier',
    transformIndexHtml(html) {
      return html.replace(
        '</head>',
        '<script>console.log("Injected!")</script></head>'
      )
    }
  }
}
Пример 2: Middleware для dev-сервера
function analyticsPlugin(): Plugin {
  return {
    name: 'request-analytics',
    configureServer(server) {
      server.middlewares.use((req, res, next) => {
        console.log(`${req.method} ${req.url}`)
        next()
      })
    }
  }
}
Пример 3: Генерация файлов во время сборки
import path from 'path'
import fs from 'fs'
import type { Plugin, ResolvedConfig } from 'vite'
function generateManifest(): Plugin {
  let config: ResolvedConfig
  
  return {
    name: 'generate-manifest',
    configResolved(resolvedConfig) {
      config = resolvedConfig
    },
    writeBundle() {
      const manifestPath = path.join(config.build.outDir, 'manifest.json')
      fs.writeFileSync(manifestPath, JSON.stringify({
        timestamp: Date.now(),
        version: process.env.npm_package_version
      }))
    }
  }
}
Для отладки используйте console.log в ваших хуках для трассировки выполнения. Методы this.warn() и this.error() обеспечивают лучшую отчётность об ошибках, чем выброс исключений.
Продвинутые паттерны плагинов и лучшие практики
Виртуальные модули
Создание модулей, которые не существуют на диске:
const virtualModuleId = 'virtual:my-module'
const resolvedVirtualModuleId = '\0' + virtualModuleId
export function virtualPlugin(): Plugin {
  return {
    name: 'virtual-plugin',
    resolveId(id) {
      if (id === virtualModuleId) {
        return resolvedVirtualModuleId
      }
    },
    load(id) {
      if (id === resolvedVirtualModuleId) {
        return `export const msg = "from virtual module"`
      }
    }
  }
}
Оптимизация производительности
Кэширование затратных преобразований:
const cache = new Map<string, string>()
function cachedTransform(): Plugin {
  return {
    name: 'cached-transform',
    transform(code, id) {
      if (cache.has(id)) return cache.get(id)
      
      const result = expensiveOperation(code)
      cache.set(id, result)
      return result
    }
  }
}
Тестируйте ваши плагины Vite с помощью Vitest, используя API createServer для проверки поведения хуков в изоляции.
Публикация и распространение вашего плагина
Следуйте этим соглашениям при публикации:
- Назовите ваш пакет 
vite-plugin-[name] - Включите 
"vite-plugin"в ключевые слова package.json - Документируйте, почему он специфичен для Vite (если использует хуки только для Vite)
 - Добавьте префиксы фреймворка, если специфичен для фреймворка: 
vite-plugin-vue-[name] 
Создайте понятный README с инструкциями по установке, примерами конфигурации и документацией API. Отправьте ваш плагин в awesome-vite, чтобы охватить сообщество.
Заключение
Создание пользовательских плагинов Vite даёт вам полный контроль над процессом сборки. Начните с простых преобразований, используя хуки вроде transform или transformIndexHtml, затем расширяйте до более сложных паттернов по мере необходимости. Plugin API мощный, но при этом доступный — большинству плагинов требуется всего несколько хуков для решения конкретных задач.
Для более глубокого изучения ознакомьтесь с официальной документацией по плагинам Vite и изучите популярные плагины в экосистеме. Ваша следующая оптимизация сборки или улучшение рабочего процесса может быть всего в одном плагине от вас.
Часто задаваемые вопросы
Да, большинство плагинов Rollup работают с Vite без модификаций. Однако плагины, которые полагаются на хук moduleParsed или требуют функциональности dev-сервера, нуждаются в адаптации для Vite. Проверьте документацию плагина на предмет заметок о совместимости с Vite.
Используйте операторы console.log в ваших хуках для трассировки потока выполнения. Методы this.warn() и this.error() обеспечивают лучшую отчётность об ошибках. Вы также можете использовать переменную окружения DEBUG с Vite для просмотра детальных логов.
Опция enforce контролирует порядок выполнения плагинов. Pre-плагины выполняются до основных плагинов Vite, post-плагины — после. Используйте pre для входных преобразований и post для модификаций вывода. Без enforce плагины выполняются в порядке их появления.
Рассмотрите публикацию, если ваш плагин решает проблему, с которой могут столкнуться другие, даже если она специализированная. Чётко документируйте его конкретный случай использования. Для действительно проектно-специфичных плагинов храните их локально или в приватном реестре.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.