Vue
Сборка: Vite 8 и SFC-компилятор
Браузер не понимает ни .vue файлов, ни TypeScript, ни тегов template и script setup. Между написанным компонентом и тем, что выполняет движок V8, лежит конвейер, который в dev-режиме отдаёт модули за миллисекунды, а в продакшене собирает минифицированный бандл. Когда правка в шаблоне мгновенно отражается на странице без перезагрузки, это работает HMR. Когда .vue превращается в три отдельных JavaScript-модуля, это работает SFC-компилятор. Этот урок открывает капот сборки: dev-сервер Vite 8, компилятор @vue/compiler-sfc и плагины, что их связывают.
- Vite 8 (2026, на Rolldown): дефолтный сборщик для новых Vue-проектов, единый Rust-бандлер для dev и прода
- @vue/compiler-sfc: разбивает .vue на render-функцию, скрипт и стили, выполняется до попадания кода в браузер
- HMR в Vite: правка template или style обновляет компонент без потери состояния приложения
- Rolldown: новый бандлер на Rust, на который Vite переходит для продакшен-сборки
- Плагины @vitejs/plugin-vue и unplugin: подключают компилятор SFC и авто-импорты в конвейер
Предварительные знания
- Опыт создания Vue-проекта и запуска dev-сервера
- Понимание ES-модулей: import и export
- Базовое представление о минификации и бандлинге
Dev-сервер и продакшен-сборка Vite
Старые бандлеры перед запуском dev-сервера собирали всё приложение в один бандл, поэтому старт линейно зависел от размера проекта. Vite устроен иначе. В dev-режиме он опирается на то, что браузер сам умеет загружать нативные ES-модули. Сервер не собирает бандл, а отдаёт каждый модуль по запросу, трансформируя его на лету: .vue превращается в JavaScript, TypeScript в JavaScript, и всё это только для тех файлов, которые браузер реально запросил. Старт сервера почти мгновенный независимо от размера кодовой базы.
Для продакшена подход меняется. Отдавать сотни мелких модулей по сети неэффективно из-за накладных расходов на запросы, поэтому Vite собирает оптимизированный бандл: объединяет модули, выкидывает неиспользуемый код через tree-shaking, минифицирует и разбивает на чанки для ленивой загрузки. Исторически Vite использовал esbuild в разработке и Rollup в продакшене, но Vite 8 (март 2026) объединил их в единый Rust-бандлер Rolldown, ускоряющий сборку крупных приложений в 10-30 раз.
| Режим | Как подаётся код | Зачем так |
|---|---|---|
| dev | Нативные ES-модули, трансформация по запросу | Мгновенный старт независимо от размера проекта |
| build | Единый оптимизированный бандл, чанки | Меньше запросов и байт у пользователя в проде |
Зависимости из node_modules Vite заранее пребандлит через esbuild при первом старте. Это нужно, потому что многие пакеты публикуются в формате CommonJS или дробятся на сотни файлов, что плохо ложится на нативные ES-модули браузера. Пребандлинг кешируется, поэтому повторные старты ещё быстрее.
Почему dev-сервер Vite стартует почти мгновенно даже на крупном проекте?
SFC-компилятор: из .vue в JavaScript
Браузер не знает, что такое .vue. Файл с блоками template, script setup и style это формат Vue, а не браузера. Превращением занимается @vue/compiler-sfc. Он разбирает файл на блоки и компилирует каждый: script setup в обычный модуль компонента, template в render-функцию, style в CSS с поддержкой scoped через генерируемые атрибуты. Результат это чистый JavaScript и CSS, которые браузер уже понимает.
Ключевая часть это компиляция шаблона. Vue не интерпретирует разметку в браузере: компилятор заранее превращает её в render-функцию, состоящую из вызовов h (создания виртуальных узлов). Эта функция при выполнении возвращает дерево виртуальных узлов, которое движок сравнивает и применяет к DOM. Работа по парсингу шаблона делается один раз во время сборки, а не на каждый рендер в рантайме.
Компилятор не просто переводит шаблон в вызовы h, он ещё и оптимизирует. Статические части помечаются и кешируются, а динамическим выставляются patch-флаги, по которым движок в рантайме знает, что именно может измениться. Поэтому скомпилированный шаблон обновляется точечно, не обходя всё дерево заново.
Во что SFC-компилятор превращает блок template?
HMR и плагины Vite
HMR (Hot Module Replacement) это то, что обновляет страницу при правке кода без полной перезагрузки и без потери состояния. Когда разработчик меняет файл, Vite перекомпилирует только его, отправляет обновлённый модуль в браузер по WebSocket, и рантайм заменяет старую версию модуля новой. Для .vue это особенно аккуратно: правка только в template или style обновляет рендер компонента, сохраняя его реактивное состояние, а правка в script setup перемонтирует компонент.
| Что изменено | Что делает HMR | Состояние |
|---|---|---|
| Только template | Перерисовывает компонент новой render-функцией | Сохраняется |
| Только style | Подменяет CSS без перерисовки | Сохраняется |
| script setup | Перемонтирует компонент | Сбрасывается |
Сама поддержка .vue не встроена в ядро Vite. Vite это универсальный сборщик, а понимание Vue даёт плагин @vitejs/plugin-vue. Плагины Vite это объекты с хуками, которые встраиваются в конвейер обработки модулей. Главные хуки это resolveId (как разрешить путь импорта), load (как получить содержимое) и transform (как преобразовать код). Именно в transform плагин Vue зовёт @vue/compiler-sfc и отдаёт скомпилированный JavaScript.
Хук transform вызывается на каждый трансформируемый модуль, поэтому тяжёлая работа в нём замедляет и dev-сервер, и сборку. Возврат null означает, что плагин этот модуль не трогает, и важно делать ранний выход по типу файла, чтобы не гонять регулярки и парсеры там, где они не нужны.
Через какой хук плагина Vite подключается компилятор SFC, превращающий .vue в JavaScript?
Связь с другими темами
Урок раскрывает конвейер, на котором держатся тесты и движок:
- Настройка проекта — Создание проекта это запуск Vite, теперь разбираем что происходит под капотом
- Тестирование — Vitest переиспользует трансформацию Vite, поэтому конфиг общий
- Под капотом: движок реактивности — Компилятор SFC порождает render-функцию, которую исполняет реактивный движок
Итог
- Vite в dev-режиме отдаёт исходники как нативные ES-модули по запросу, трансформируя каждый файл на лету, поэтому старт сервера не зависит от размера проекта
- Для продакшена Vite собирает оптимизированный бандл, делая tree-shaking и минификацию, в новых версиях через бандлер Rolldown на Rust
- SFC-компилятор @vue/compiler-sfc разбирает .vue на блоки и превращает template в render-функцию, а script setup в обычный модуль компонента
- Шаблон компилируется в render-функцию из вызовов h, а не интерпретируется в браузере, что переносит работу со времени выполнения на время сборки
- HMR заменяет изменённый модуль на лету: правка шаблона или стиля обновляет компонент, по возможности сохраняя его состояние
- Плагины Vite (например @vitejs/plugin-vue) встраивают компилятор SFC и другие трансформации в конвейер через хуки resolve, load и transform
Связанные уроки
- vue-41-testing — Vitest переиспользует тот же конвейер трансформации Vite, что разбирается здесь
- vue-44-internals-future — Понимание компилятора SFC ведёт к внутреннему устройству движка и будущей компиляции Vapor