Как работает компиляция Vue Core

05 марта 2026
Автор

Олег Марков

Введение

Vue.js – это один из популярнейших фреймворков для создания современных веб-приложений. Его основу составляет ядро (Vue Core) и система компиляции шаблонов. Понимание того, как происходит компиляция внутри Vue Core помогает разработчикам оптимизировать свои компоненты, выявлять узкие места, а также лучше разбираться в механизмах реактивности и обновлений, которые дает этот фреймворк.

В этой статье я подробно расскажу, как Vue компилирует шаблоны, превращая их в быстрый JavaScript-код, который обновляет DOM с минимальными затратами. Покажу основные этапы компиляции на примерах кода, разберу внутренние функции и архитектуру процесса. Вы поймете разницу между рантайм- и ahead-of-time-компиляцией, узнаете о структуре AST и увидите, что происходит “под капотом” при работе с вашими .vue файлами.

Как устроена система компиляции Vue

Vue Core компилирует шаблоны компонентов в render-функции на JavaScript. Еще проще — ваш HTML-привычный синтаксис становится чистым JS, который умеет максимально эффективно обновлять интерфейс.

Давайте поговорим о ключевых частях этого процесса.

Зачем вообще нужна компиляция?

Vue — декларативный фреймворк: вы описываете, как должен выглядеть интерфейс, а что происходит в браузере «под капотом» — скрыто. Компиляция шаблонов позволяет преобразовать декларативный синтаксис Vue в низкоуровневую инструкцию для реактивного движка, который быстро меняет только изменившиеся части DOM.

  • Простые шаблоны проще писать и читать.
  • Генерация оптимизированного кода происходит автоматически.
  • Меньше ошибок — не нужно вручную писать render-функции.

Разбираться в тонкостях компиляции ядра Vue — это продвинутый навык, который позволяет лучше понимать, как работает фреймворк изнутри. Но для создания полноценных приложений, необходимо также понимать, как устроена архитектура, как управлять состоянием и как организовать маршрутизацию. Если вы хотите углубить свои знания о Vue и стать экспертом, приходите на наш большой курс Vue.js 3, Vue Router и Pinia. На курсе 173 уроков и 21 упражнение, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Два основных режима компиляции: в рантайме и на этапе сборки

Рантайм-компиляция (Runtime compilation)

В этом случае браузер получает исходный шаблон (обычно это строка внутри опции template). Прямо во время выполнения приложение берет этот шаблон и компилирует его на лету в render-функцию.

new Vue({
  el: '#app',
  template: '<div>{{ message }}</div>',
  data: {
    message: 'Hello'
  }
})
// Шаблон компилируется уже в браузере

Преимущества:

  • Гибкость — шаблон можно формировать динамически, например, на сервере.

Недостатки:

  • Компилятор загружает вес итогового бандла на ~10-15кб.
  • Производительность чуть ниже, чем у pre-compiled рендер-функции.

Компиляция во время билда (Ahead-of-Time, AOT)

Второй подход — компиляция на этапе сборки (чаще всего через webpack-плагин vue-loader или Vite). Тогда .vue шаблоны превращаются в JS render-функции ещё ДО передачи кода браузеру.

// Внутри Single File Component (.vue)
// <template>
//   <div>{{ message }}</div>
// </template>

// vue-loader превратит это в функцию render.
// В prod-сборке браузер уже получает только render-функцию, никакой лишней работы на клиенте!

Преимущества:

  • Максимальная производительность.
  • Нет лишнего кода компилятора в вашем бандле.
  • Ранние ошибки в шаблоне будет видно на этапе сборки.

Недостатки:

  • Нет возможности динамически менять шаблон на клиенте.

Рекомендация: во всех production-проектах используйте AOT-компиляцию (с vue-loader, Vite, Rollup-плагином — не важно). Рантайм-компиляция нужна только для особых случаев.

Этапы компиляции в Vue Core

Давайте разберем пошагово, что происходит с вашим шаблоном до его «оживления» в браузере.

Этап 1. Парсинг: шаблон превращается в AST

Первый шаг компилятора — это парсинг шаблона и построение абстрактного синтаксического дерева (AST — Abstract Syntax Tree).

Что такое AST в Vue?

AST — это дерево JavaScript-объектов, где каждая нода — тег, атрибут, директива, текст. Компилятор не работает с текстом напрямую, а с уже разобранной структурой.

Вот так это выглядит на псевдокоде:

<div>
  <h1>{{ title }}</h1>
  <button @click="increment">Добавить</button>
</div>

AST для такого шаблона будет напоминать:

{
  type: 'Element',
  tag: 'div',
  children: [
    {
      type: 'Element',
      tag: 'h1',
      children: [
        {
          type: 'Interpolation',
          content: 'title'
        }
      ]
    },
    {
      type: 'Element',
      tag: 'button',
      props: [
        {
          name: 'onClick',
          value: 'increment'
        }
      ],
      children: [
        {
          type: 'Text',
          content: 'Добавить'
        }
      ]
    }
  ]
}

AST строится специальной функцией-парсером, которая разбирает входной HTML на узлы-структуры.

Этап 2. Трансформация дерева: работа оптимизаторов

AST можно анализировать и модифицировать. Следующим шагом Vue-компилятор применяет преобразования (трансформации):

  • Распознается, какие части шаблона статичны (static content hoisting).
  • Обнаруживаются циклы (v-for) и условия (v-if, v-else).
  • Директивы Vue переводятся во внутренние инструкции.

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

Пример — оптимизация статических блоков:

<div>
  <span>Это всегда статично</span>
  <span>{{ динамика }}</span>
</div>

В AST первый <span> можно вынести в отдельную переменную, чтобы не пересчитывать его при каждом рендере.

Этап 3. Генерация кода (Codegen)

Теперь пришло время превращать AST в финальную render-функцию. Эта функция — обычный чистый JavaScript, который создает виртуальное дерево DOM (VNode) для реактивного движка Vue.

Посмотрим на реальный пример.

Исходный шаблон

<div>
  <p>{{ msg }}</p>
</div>

Итоговый JS к которому ведет компиляция (упрощенно):

function render(ctx, cache) {
  return _createElementVNode(
    'div',
    null,
    [
      _createElementVNode(
        'p',
        null,
        [
          _toDisplayString(ctx.msg) // ctx — ссылка на реактивные данные
        ]
      )
    ]
  );
}
  • _createElementVNode — вспомогательная функция Vue для создания VNode-ноды.
  • _toDisplayString превращает переменную во что-то, что можно вставить в DOM (например, экранированную строку).

Благодаря этому, actual DOM не обновляется весь, а только те участки, что были реально изменены (msg).

Немного глубже: функции компилятора Vue

В реальной жизни при работе с Vue Core и его внутренностями вы встретите такие функции и пакеты:

  • @vue/compiler-dom — основной пакет для компиляции шаблонов во frontend.
  • compile — главная функция, принимающая строку-шаблон, возвращающая render-функцию.
  • parse — разбирает шаблон и возвращает AST.
  • transform — преобразует AST, оптимизируя его.
  • generate — превращает AST в JavaScript-код рендера.

Покажу порядок вызова:

import { compile } from '@vue/compiler-dom';

const { code } = compile('<div>{{ message }}</div>');

// В code теперь содержится JS render-функция в виде строки

Если хочется увидеть AST для любого шаблона, это можно сделать вручную:

import { baseParse } from '@vue/compiler-core';

const ast = baseParse('<div><p>Привет, {{ name }}</p></div>');
console.log(JSON.stringify(ast, null, 2));
// Вывод: подробное дерево элементов, текстовых узлов и интерполяций

Особенности и возможности компилятора Vue

Генерация SSR-кода

Если вы используете Vue для SSR (server-side rendering), шаблоны компилируются по-другому — AST превращается в код, который можно запустить на сервере для генерации HTML-строк.

Для этого служит пакет @vue/compiler-ssr.

Работа с директивами, слотами и v-bind

Компилятор Vue умеет разбирать и превращать любые стандартные директивы (v-if, v-for, v-show, v-bind, v-on) в быстрые JS-выражения.

Пример кода с условиями:

<div>
  <span v-if="ok">Да</span>
  <span v-else>Нет</span>
</div>

Компиляция превратится примерно в:

// Псевдокод рендера
function render(ctx) {
  return _createElementVNode(
    'div',
    null,
    [
      ctx.ok
        ? _createElementVNode('span', null, 'Да')
        : _createElementVNode('span', null, 'Нет')
    ]
  )
}

Слоты, директивы, даже пользовательские компоненты — всё это превращается в JS-функции, которые умеют быстро реагировать на реактивность «снаружи».

Интересные оптимизации: patchFlag, static hoisting

Vue-компилятор генерирует специальные подсказки (patchFlags), чтобы движок понимал, как лучше обновлять виртуальное дерево DOM. Это делает работу вашего приложения быстрее даже на больших интерфейсах.

static hoisting — вынесение неизменяемых частей шаблона во внешние переменные, чтобы не пересоздавать их каждый раз.

patchFlag — специальные биты, которые указывают, какие свойства в VNode могут меняться.

Как изучать, что происходит внутри — инструменты и лайфхаки

  • Воспользуйтесь онлайн-песочницей: https://template-explorer.vuejs.org/ — сюда можно вставить любой шаблон и увидеть AST, оптимизации и финальный render-код.
  • Можно смотреть сгенерированный render-код для компонентов через vue-loader (ищите render.js файлы рядом с вашими .vue-компонентами после сборки).

Практический пример: end-to-end

Допустим, у вас есть такой компонент:

<template>
  <ul>
    <li v-for="item in list" :key="item.id">{{ item.text }}</li>
  </ul>
</template>

В ходе компиляции происходят такие шаги:

  1. Парсинг: создается AST дерева — ul с вложенными li, где есть v-for и интерполяция.
  2. Трансформация: v-for луп распознается как специальная структура для itераций.
  3. Генерация рендер-функции:
function render(ctx, cache) {
  return _createElementVNode(
    "ul", 
    null, 
    _renderList(ctx.list, (item) =>
      _createElementVNode("li", { key: item.id }, _toDisplayString(item.text))
    )
  )
}
  • _renderList — вспомогательная функция для циклов.
  • Каждый li получает свой уникальный ключ.

Как видите, шаблон превращается в чистый, оптимизированный JS, который максимально быстро обновляет только изменяющиеся строки или элементы списка.

Заключение

Система компиляции в Vue Core — одна из сильнейших сторон этого фреймворка. Она позволяет писать выразительные и читаемые шаблоны на близком к HTML синтаксисе, а потом превращает их в сверхбыстрые JavaScript-функции, заточенные на минимальный объем изменений DOM.

Компиляция проходит через три этапа: парсинг (в AST), трансформация (оптимизации и подсказки для движка), и генерация рендер-кода. В итоге даже самый большой Vue-проект будет работать быстро, потому что обновляет только нужные части интерфейса.

Осознанное понимание механизма компиляции дает вам возможность находить и устранять узкие места, писать более чистый и “быстрый” код, использовать дополнительные возможности оптимизации.

Понимание принципов компиляции ядра, безусловно, полезно, но без знаний архитектуры приложений, маршрутизации и управления состоянием не получится создавать сложные и поддерживаемые Vue приложения. На нашем курсе Vue.js 3, Vue Router и Pinia вы получите все необходимые знания и навыки. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир Vue прямо сегодня.

Частозадаваемые технические вопросы по теме компиляции Vue Core

Почему при использовании runtime-only сборки Vue нельзя использовать опцию template в new Vue?

Vue runtime-only не содержит компилятора шаблонов. Если вы передадите строку в опции template, Vue не сможет её обработать. Используйте render-функцию или собирайте проект через vue-loader/Vite, чтобы шаблон был скомпилирован в JS заранее.

Как посмотреть итоговую render-функцию для своего шаблона?

Можно воспользоваться https://template-explorer.vuejs.org/ — вставьте шаблон и посмотрите, во что он транслируется. Также для Single File Component итоговая функция обычно видна рядом с компонентом после сборки (render.js или атрибут render в исходном JS-файле).

Что делать, если хочется динамически собирать шаблоны на клиенте?

Используйте специальную версию Vue (vue@2: разница между vue.runtime.js и vue.js), а для Vue 3 — подключайте пакет @vue/compiler-sfc и используйте API типа compile. Но старайтесь избегать этого в prod, только если есть реальный use-case.

Как добавить свою кастомную директиву, чтобы она корректно работала после компиляции?

Кастомные директивы, объявляемые через app.directive, автоматически используются в render-функциях после компиляции. Главное — чтобы имя директивы совпадало с используемым в шаблоне.

Почему при ошибках в шаблоне бывают сложные для понимания сообщения?

Ошибки, которые возникают на этапе компиляции, часто указывают на проблему парсинга или невозможность корректного построения AST. Совет: пользуйтесь редакторами с поддержкой linting для Vue (Vetur, Volar) — они подсказывают ошибки заранее.

Стрелочка влевоОрганизация циклов и итераций во VueВычисляемые свойства computed во Vue.jsСтрелочка вправо

Постройте личный план изучения Vue до уровня Middle — бесплатно!

Vue — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Vuex - полное руководство по управлению состоянием во Vue приложенияхРеактивные ссылки ref - полный разбор для разработчиковРеактивные объекты reactive-objects - подробное руководство с примерамиРеактивные переменные - концепция reactive и практические примерыМеханизм Provide Inject - как он работает и когда применятьPinia современный менеджер состояния для VueЛокальное состояние local state в веб разработкеГлобальное состояние в приложениях - global state
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
Функция append в Go GolangОтображение компонента mounted - практическое руководствоХуки жизненного цикла компонентов - полное руководство для разработчиковУничтожение компонента destroyed - как правильно очищать ресурсы и подпискиИнициализация данных в состоянии created - как и когда подготавливать данные в приложенииОбновление компонента beforeUpdate во VueМонтирование компонента - хук beforeMount в VueРазрушение компонента во Vue - beforeDestroy и beforeUnmountСоздание экземпляра beforeCreate - полный разбор жизненного цикла
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Слоты компонента - концепция и практическое использованиеРегистрация компонентов component-registration в приложениях с внедрением зависимостейProps компонента в React - полный разбор с примерамиФункциональные компоненты в React - функциональный подход к построению интерфейсовСобытия компонента - events в современных интерфейсахДинамические компоненты - dynamic-componentsСоздание компонента component - практическое руководствоАсинхронные компоненты async-components - практическое руководство
Наблюдатели watchers - от паттерна до практических реализацийУправление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsШаблоны Vue templates - практическое руководство для разработчиковИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueРеактивность Vue reactivity - как это работает под капотом и как этим пользоватьсяПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueОпции компонента в Go - паттерн component-optionsРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreВычисляемые свойства computed во Vue.jsСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueОсновы Vue - vue-basics для уверенного стартаИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueТелепортация - архитектура и реализация в серверных приложенияхРабота с teleport для управления DOM во VueSuspense в React - управление асинхронными данными и ленивой загрузкойПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиПлагины Vue vue-plugins - полное практическое руководствоРуководство по nextTick для работы с DOMМиксины - mixins в современном программированииJSX в Vue с использованием плагина vue-jsxСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьКастомные элементы - Custom Elements в современном JavaScriptИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Vue 3 и Pinia

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий