Перейти к основному содержимому

5.01. Vue

Разработчику Архитектору

Vue

Vue.js — это JavaScript-фреймворк, предназначенный для построения пользовательских интерфейсов и одностраничных приложений. Его ключевая особенность — прогрессивность. Эта характеристика означает, что Vue может применяться как в минимальной форме — как библиотека для декларативного рендеринга на основе данных, так и в масштабах крупного приложения с полноценной архитектурной поддержкой: маршрутизацией, управлением состоянием, сборкой, типизацией и инструментальной интеграцией. Подобная гибкость обеспечивает постепенную адаптацию: разработчик может начать с внедрения Vue в уже существующий проект, не переписывая его целиком, а затем наращивать сложность и охват по мере необходимости.

Отличительной чертой Vue является стремление к балансу между мощью, простотой и предсказуемостью. В отличие от Angular, где вводится собственный DSL, множество специализированных концепций и обязательная строгая архитектура с DI-контейнером, Vue делает ставку на минимальное расширение привычных веб-технологий. Для старта достаточно знания HTML и JavaScript. Это не означает примитивности — фреймворк предоставляет богатые средства для масштабирования, но не принуждает к их использованию с первых строк кода. Typescript поддерживается на уровне первоклассного гражданина и может включаться как опциональный, но рекомендуемый слой над JavaScript-ядром, особенно в крупных проектах.

Исторический контекст и эволюция

Vue.js был представлен Евгением Ю (Evan You) в 2014 году. До этого он работал в Google над проектами на AngularJS и столкнулся с рядом ограничений: высокой пороговой сложностью, необходимостью глубокого погружения в фреймворковую экосистему и недостаточной гибкостью для постепенного внедрения. Идея Vue возникла как попытка создать средство, сочетающее лучшие аспекты Angular (например, двустороннюю привязку данных и реактивность) с лёгкостью и декларативностью подходов, подобных React. При этом Vue изначально позиционировался как инструмент, не вынуждающий разработчика отказываться от привычной модели разработки на HTML, CSS и JS.

Первая стабильная версия — Vue 1 — быстро нашла отклик у сообщества благодаря своей лаконичности и эффективности. Она уже включала реактивную систему, директивы и компонентную модель, но не имела официального маршрутизатора или менеджера состояний; эти компоненты появлялись как отдельные плагины.

Vue 2, выпущенный в 2016 году, стал прорывом. Он основывался на полностью переписанной реактивной системе, использовавшей перехват доступа к свойствам через Object.defineProperty. Это позволило реализовать реактивность без явных вызовов обновления, а также улучшить производительность и предсказуемость. В Vue 2 появились официальные библиотеки: Vue Router для клиентской навигации и Vuex для централизованного управления состоянием. Архитектура однофайловых компонентов (.vue-файлов) стала де-факто стандартом для проектов средней и высокой сложности. Инструментарий (vue-cli) обеспечивал быструю настройку сборки, включая поддержку webpack, Babel, препроцессоров и тестирования.

Vue 3, представленный в 2020 году и ставший стабильным в 2022, знаменует собой следующую эволюционную ступень. Основные изменения затронули как внутреннюю архитектуру, так и API. Реактивная система была переписана с использованием прокси (Proxy), что позволило избавиться от ограничений Object.defineProperty (например, невозможности отслеживать добавление/удаление свойств у объектов без дополнительных вызовов вроде Vue.set). Vue 3 стал модульным на уровне ядра: компилятор и реактивная система выделены в отдельные пакеты, что упрощает tree-shaking и уменьшает размер итоговой сборки. Был введён Composition API — альтернативный Options API способ организации логики компонента, ориентированный на гибкость и композицию. Одновременно с этим родился Vite — новый инструмент для сборки и разработки, использующий нативные ES-модули в браузере и демонстрирующий порядки прироста в скорости запуска и обновления приложения по сравнению с webpack-основанными решениями.

Архитектурная основа

Vue.js не навязывает строгую MVC- или MVVM-архитектуру, но в своей основе реализует идеи паттерна Model-View-ViewModel. В этой модели ViewModel выступает как связующее звено между View (представлением, то есть DOM) и Model (данными приложения). Ключевое свойство ViewModel — реактивность: при изменении данных во ViewModel автоматически перестраивается соответствующая часть View, и наоборот — изменения во View (например, ввод текста в поле) могут обновлять данные в ViewModel.

Этот механизм устраняет необходимость вручную синхронизировать DOM и состояние приложения, как это делается при использовании jQuery или аналогичных библиотек низкого уровня. Разработчик описывает что должно отображаться, а не как изменять DOM-элементы. Vue берёт на себя задачу отслеживания зависимостей между данными и DOM, и выполняет минимально необходимые обновления.

Важно подчеркнуть: реактивность в Vue достигается без аннотаций, декораторов или специальных классов, как в некоторых других фреймворках (например, Knockout.js требует объявления observable). Переменные, объявленные внутри компонента или экземпляра Vue, становятся реактивными автоматически — при условии, что они были известны на момент инициализации. Это создаёт впечатление «магии», но на деле опирается на детально продуманную систему отслеживания доступа к свойствам и вызовов геттеров/сеттеров.

Реактивная система

Реактивность — центральный механизм Vue. Её цель — установить и поддерживать связи между источниками данных и точками их отображения. Когда данные изменяются, система должна знать, какие части интерфейса зависят от этих данных, и обновить только их.

В Vue 2 реактивность строилась поверх Object.defineProperty. При инициализации экземпляра Vue он рекурсивно обходил все свойства объекта data, преобразуя их в геттеры и сеттеры. При первом рендеринге шаблона происходил «сбор зависимостей»: при вычислении выражений (например, {{ message }}) вызывался геттер, который регистрировал текущий «эффект» (рендер) как подписчика на это свойство. При последующем присваивании (this.message = 'новое') вызывался сеттер, который, в свою очередь, уведомлял всех подписчиков о необходимости повторного вычисления.

Этот подход работал эффективно, но имел ограничения: динамическое добавление новых свойств в реактивный объект требовало явного вызова Vue.set, поскольку Object.defineProperty не мог перехватить присваивание новому свойству.

Vue 3 устранил это ограничение, перейдя на Proxy. Объект-прокси оборачивает исходный объект и перехватывает все операции чтения, записи, удаления и проверки наличия свойств. Это позволяет отслеживать динамические изменения без дополнительных вызовов, а также поддерживать реактивность для массивов, Map, Set и других структур более естественно.

Для управления реактивностью на уровне кода Vue 3 предоставляет две основные утилиты:

  • reactive() — создаёт глубоко реактивный объект (проксирует весь объект и его вложенные свойства);
  • ref() — оборачивает любое значение (включая примитивы) в объект с единственным свойством .value, что позволяет отслеживать изменения даже для строк, чисел или булевых значений.

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

Компонентная модель

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

Компоненты организованы в иерархию: корневой компонент содержит дочерние, те — своих потомков, и так далее. Данные передаются от родителя к потомку через props (свойства), а события — от потомка к родителю через emit (выброс событий). Это создаёт однонаправленный поток данных, который упрощает отладку и предсказуемость.

Наиболее распространённый формат компонента — однофайловый компонент (Single-File Component, SFC), с расширением .vue. Такой файл содержит три основных блока:

  • <template> — декларативное описание разметки, использующее расширенный HTML с директивами;
  • <script> — логика компонента, может быть на JavaScript или TypeScript, поддерживает как Options API, так и Composition API;
  • <style> — стили, локально scoped по умолчанию (через атрибут scoped), что предотвращает конфликты имён классов между компонентами.

SFC не является обязательным — компонент можно определить и в виде чистого JavaScript-объекта с шаблоном в виде строки. Однако .vue-файлы обеспечивают лучшую организацию кода, поддержку статической типизации, автодополнение и инструментальную интеграцию (например, через Volar в VS Code), и считаются стандартом де-факто для проектов на Vue.

Директивы

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

Рассмотрим ключевые встроенные директивы:

  • v-if, v-else-if, v-else — условный рендеринг. Элемент присутствует в DOM только тогда, когда выражение истинно. При ложном значении элемент полностью удаляется из дерева, а не скрывается через CSS. Это важно для производительности при работе с тяжёлыми компонентами или большими списками.

  • v-for — рендеринг списков. Принимает массив или объект и создаёт копию элемента для каждого элемента итерации. Требует указания уникального key, который помогает Vue идентифицировать узлы при их перемещении, добавлении или удалении, и эффективно обновлять DOM с минимальным количеством операций.

  • v-bind (сокращённо :) — динамическая привязка атрибутов HTML. Позволяет связать значение атрибута (например, href, class, style) с выражением JavaScript. Особенно мощна при работе с объектами и массивами для классов и стилей: например, { active: isActive } добавит класс active, если isActive истинно.

  • v-on (сокращённо @) — прослушивание DOM-событий. Выражение — это либо имя метода, либо инлайновая функция. Поддерживает модификаторы: .prevent, .stop, .once, .capture, а также клавиатурные — .enter, .esc и др.

  • v-model — синтаксический сахар для двусторонней привязки данных в формах. Комбинирует v-bind:value и v-on:input (или другие события в зависимости от типа элемента), обеспечивая автоматическую синхронизацию между полем ввода и переменной в компоненте. Работает с <input>, <textarea>, <select>, а также с кастомными компонентами при правильной реализации события update:modelValue.

Жизненный цикл компонента

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

В Options API хуки — это методы компонента с зарезервированными именами: beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted.

Например, в created данные уже реактивны, но DOM ещё не построен; в mounted компонент уже в DOM, и можно обращаться к нативным элементам (например, инициализировать стороннюю библиотеку); в beforeUnmount — последняя возможность выполнить очистку (отписаться от событий, остановить таймеры, закрыть соединения).

В Composition API хуки доступны как отдельные функции: onMounted, onUnmounted, onBeforeUpdate и т.д., что делает их композируемыми и переиспользуемыми в составе custom composables.

Управление жизненным циклом — важный аспект для предотвращения утечек памяти и обеспечения корректного поведения приложения, особенно при работе с внешними ресурсами.

Модульность и расширяемость

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

  • Vue Router — официальный маршрутизатор. Обеспечивает навигацию на клиенте, ленивую загрузку компонентов, вложенную маршрутизацию, защиту маршрутов и интеграцию с состоянием приложения.

  • Pinia — современный менеджер состояния, рекомендуемый для Vue 3 (Vuex 4 остаётся совместимым, но не развивается). Pinia основан на Composition API, не требует мутаций, поддерживает TypeScript «из коробки», и позволяет организовывать состояние в виде хранилищ с чёткими границами ответственности. Каждое хранилище — это реактивный объект с state, getters и actions, который может быть импортирован и использован непосредственно в компонентах.

  • Vite — инструмент для сборки и разработки, разработанный тем же Евгением Ю. Использует нативные ES-модули в режиме разработки, что устраняет необходимость в предварительной сборке: сервер запускается мгновенно, а обновления происходят за счёт HMR (Hot Module Replacement) на уровне модуля. Для продакшена Vite использует Rollup, обеспечивая оптимизированные, минифицированные и tree-shaken сборки.

  • Vue DevTools — расширение для браузера, позволяющее инспектировать дерево компонентов, отслеживать изменения состояния, просматривать события и профилировать производительность. Интегрируется как с Vue 2, так и с Vue 3.

  • Vue Test Utils — официальная утилита для unit- и компонентного тестирования, совместимая с Jest, Vitest и другими тест-раннерами.

Эта модульность подчёркивает философию Vue: набор согласованных, но независимых инструментов, из которых разработчик сам собирает стек под свои нужды.


Options API и Composition API

Vue предоставляет два способа описания поведения компонента: Options API и Composition API. Они дополняют друг друга, позволяя выбирать стиль в зависимости от масштаба проекта, требований к поддержке и предпочтений команды.

Options API — это классический подход, заложенный ещё в Vue 1 и доминировавший в Vue 2. Логика компонента структурируется по категориям: data, computed, methods, watch, props, lifecycle hooks и т.д. Каждая из этих «опций» — отдельное свойство объекта, передаваемого в defineComponent() или Vue.component(). Такая организация интуитивно понятна новичкам: всё, что относится к данным, находится в одном месте, всё, что относится к вычисляемым свойствам — в другом. Это упрощает навигацию в малых компонентах.

Однако при росте сложности (например, при реализации нескольких связанных фич в одном компоненте — аутентификация, фильтрация, загрузка данных) логика одной фичи размазывается по разным опциям. Чтобы понять, как работает «поиск», приходится переключаться между data, computed, methods, watch и хуками. Это нарушает принцип cohesion — связанности кода по смыслу, а не по типу.

Composition API, введённый в Vue 3, решает эту проблему. Он позволяет группировать логику по функциональным блокам — composables. Вместо разделения по категориям, разработчик объединяет переменные, вычисляемые свойства, методы и побочные эффекты, относящиеся к одной задаче, в отдельную функцию. Например, useAuth(), useSearch(), usePagination() — каждая возвращает набор реактивных ссылок и функций, которые затем используются в компоненте.

Composition API построен на базовых примитивах: ref, reactive, computed, watch, watchEffect, а также хуках жизненного цикла в виде функций (onMounted, onUnmounted). Это делает логику компонента более декларативной и выразительной, особенно при работе с асинхронными операциями, сложными зависимостями или повторным использованием.

Важно: Composition API не заменяет Options API. Оба доступны в Vue 3, и можно смешивать их в рамках одного компонента (хотя это не рекомендуется). Более того, <script setup>, синтаксический сахар для Composition API, стал стандартом для новых проектов благодаря своей лаконичности и улучшенной поддержке TypeScript.

Однофайловые компоненты

Однофайловый компонент (SFC) — это архитектурный выбор, обеспечивающий максимальную локальность и сопровождаемость. Файл .vue — это валидный HTML-файл, распознаваемый инструментами сборки (в первую очередь — vue-loader для webpack и @vitejs/plugin-vue для Vite). При сборке каждый блок обрабатывается соответствующим препроцессором: шаблон — компилятором Vue в render-функцию, скрипт — транспайлером (Babel/TypeScript), стили — CSS-препроцессором (Sass, Less и др.).

Современный SFC часто использует <script setup> — компиляторную оптимизацию, позволяющую объявлять компонент в более компактной форме. Вместо экспорта объекта с setup()-функцией, весь код внутри <script setup> автоматически становится телом setup(), а импортированные компоненты и объявленные переменные становятся доступны в шаблоне без явного возврата. Это устраняет шаблонный код и повышает читаемость.

Например:

<script setup>
import { ref, computed } from 'vue'
import UserProfile from './UserProfile.vue'

const name = ref('Тимур')
const greeting = computed(() => `Привет, ${name.value}!`)
</script>

<template>
<div>
<input v-model="name" />
<p>{{ greeting }}</p>
<UserProfile :name="name" />
</div>
</template>

Здесь UserProfile автоматически регистрируется как дочерний компонент, name и greeting — доступны в шаблоне. Нет необходимости писать return { name, greeting, UserProfile }.

Дополнительно SFC поддерживает:

  • <style scoped> — стили применяются только к текущему компоненту. Реализуется через добавление уникального атрибута data-v-xxxxxx ко всем селекторам и элементам;
  • <style module> — альтернативный подход, при котором классы становятся объектом в script, и используются как динамические имена (полезно при работе с CSS-in-JS-библиотеками или строгой типизацией);
  • атрибуты lang="ts", lang="scss", lang="pug" — указание языка для соответствующего блока;
  • <custom-block> — возможность добавлять собственные блоки (например, <i18n> для локализации), обрабатываемые через кастомные Vite- или webpack-плагины.

Такая гибкость делает SFC полноценной платформой для построения компонентов.

Управление стилями

Стилизация в Vue решает две ключевые задачи: изоляция и переиспользование. Изоляция достигается через scoped-стили, когда компилятор автоматически добавляет уникальный атрибут ко всем элементам компонента и модифицирует CSS-селекторы, чтобы они сопоставлялись только с этими элементами. Это дополнительный уровень защиты от побочных эффектов.

Однако scoped не изолирует глубоко вложенные компоненты — для этого используются «глубокие» селекторы (:deep()), а также псевдоэлементы ::v-deep, ::v-global (устаревшие, но ещё встречаются). Для стилизации сторонних библиотек или глобальных состояний (например, body, html) применяется отдельный <style> без scoped.

CSS Modules интегрируются через <style module>. В этом случае классы из блока стилей становятся объектом classes в компоненте, и используются как динамические имена: <div :class="classes.container">. Преимущество — строгая типизация в TypeScript и отсутствие коллизий имён даже при совпадении строк.

Vue также поддерживает CSS-переменные, препроцессоры (Sass, Less, Stylus) и post-процессоры (PostCSS), включая autoprefixer и cssnano. Это позволяет встраивать Vue в существующие дизайн-системы и использовать современные подходы к стилизации: utility-first (Tailwind), atomic CSS или компонентные темы через CSS-in-JS (хотя последнее менее характерно для Vue-экосистемы, чем для React).

Инструментальная поддержка

Vite — принципиально иной подход к разработке. В режиме разработки Vite запускает локальный сервер, который обслуживает исходные файлы без сборки. Браузер загружает модули через нативные <script type="module">, а Vite перехватывает запросы, транспилирует .vue, .ts, .jsx «на лету» и предоставляет их браузеру. Это устраняет этап «сборки всего приложения перед стартом», и время запуска сокращается с десятков секунд до нескольких сотен миллисекунд.

Горячая замена модулей (HMR) в Vite работает на уровне отдельных модулей. При изменении стилей — обновляются только стили; при изменении логики — сохраняется состояние компонента (например, введённый в поле текст). Это создаёт ощущение мгновенной обратной связи, критически важное для продуктивной разработки.

Для продакшена Vite использует Rollup — инструмент, оптимизированный для создания библиотек и приложений с минимальным размером. Он выполняет code splitting, tree shaking, минификацию и генерацию sourcemap’ов. Профили (production, development, staging) настраиваются через vite.config.ts, а плагины (для анализа bundle, интеграции с backend, SSR) подключаются декларативно.

Vue DevTools — необходимый инструмент для отладки. Помимо инспекции дерева компонентов и просмотра props/state, он позволяет:

  • отслеживать изменения реактивных данных в реальном времени;
  • анализировать события, включая пользовательские emit;
  • профилировать производительность рендеринга (отдельно для mount, update, patch);
  • просматривать состояние Pinia/Vuex;
  • эмулировать SSR и проверять гидратацию.

Для Vue 3 DevTools полностью переписан и работает как standalone-приложение (через @vue/devtools), что особенно полезно при разработке на устройствах без расширений (мобильные браузеры, Electron).

Серверный рендеринг (SSR) и статическая генерация (SSG)

Vue изначально ориентирован на клиентский рендеринг (CSR), но поддерживает SSR — рендеринг HTML на сервере. Это критично для SEO, социальных превью и первой загрузки на слабых устройствах. При SSR Vue-приложение выполняется в Node.js-окружении, рендерит HTML, отправляет его клиенту, а затем «оживляет» — процесс, называемый hydration: Vue присоединяет обработчики событий и берёт управление на себя, не пересоздавая DOM.

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

Nuxt.js — официально рекомендуемый фреймворк для SSR и SSG в экосистеме Vue. Он автоматизирует всю инфраструктуру: роутинг на основе файловой системы, prefetch данных, code splitting, кэширование, генерация статики и развёртывание в serverless-средах.

Nuxt 3, построенный на Vue 3 и Vite, объединяет SSR, SSG и CSR в едином workflow. Команда nuxt generate создаёт статический сайт (SSG), nuxt build && nuxt start — полноценное SSR-приложение, а nuxt dev — мгновенную разработку с HMR. Все компоненты в Nuxt — .vue-файлы, но с расширенным API: useAsyncData, useFetch, definePageMeta, useHead и др.

Особое внимание уделено производительности: автоматическая оптимизация изображений через @nuxt/image, ленивая загрузка компонентов, встроенная поддержка webp, avif, prefetch ссылок и т.д. Nuxt также предоставляет механизм composables первого уровня — каждый useXxx в каталоге composables/ автоматически доступен во всём приложении.

Тестирование и типизация

Vue поддерживает все уровни тестирования: unit, компонентное, интеграционное, E2E.

Для unit- и компонентного тестирования используется Vue Test Utils — низкоуровневая утилита, предоставляющая API для монтирования компонентов в изолированном DOM-окружении (через jsdom), эмуляции событий, проверки props и состояния. В сочетании с Vitest (быстрым тест-раннером от создателей Vite) достигается скорость выполнения тестов, сопоставимая с TDD в реальном времени.

Компонентные тесты часто фокусируются на:

  • корректности рендера при заданных props и state;
  • реакции на пользовательские события (trigger('click'));
  • вызовах emit и внешних функций;
  • работе с асинхронными операциями (например, загрузкой данных).

TypeScript интегрируется на уровне ядра. Vue 3 написан на TypeScript, и его типы полностью покрывают API. При использовании <script setup lang="ts"> IDE предоставляет автодополнение, проверку типов и рефакторинг «из коробки». Props могут быть строго типизированы через defineProps<{ name: string }>(), emits — через defineEmits<{ (e: 'submit', data: FormData): void }>().

Pinia особенно выигрывает от типизации: хранилища, созданные через defineStore, возвращают полностью типизированный объект, включая state, getters и actions. Это исключает ошибки при обращении к несуществующим полям и упрощает навигацию по состоянию.


От минимального приложения к полноценному SPA

Разработка на Vue может начинаться с одного HTML-файла и одной строки подключения CDN. Это соответствует философии прогрессивного внедрения: не требуется настройка сборки, TypeScript, роутера или менеджера состояний. Простой пример:

<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">{{ message }}</div>

<script>
const { createApp, ref } = Vue
createApp({
setup() {
const message = ref('Привет из Vue!')
return { message }
}
}).mount('#app')
</script>
</body>
</html>

Этот код демонстрирует минимальный экземпляр приложения: createApp() создаёт корневой контекст, setup() объявляет реактивное состояние, mount() связывает его с DOM-узлом. Несмотря на простоту, здесь уже задействованы ключевые механизмы: реактивность (ref), компиляция шаблона, жизненный цикл.

При росте требований к проекту следующие шаги включают:

  1. Добавление компонентов — вынос логики в .vue-файлы, использование import/export, регистрация через components.
  2. Введение маршрутизации — подключение vue-router, определение маршрутов, использование <router-view> и <router-link>, защита маршрутов через guards.
  3. Центральное управление состоянием — создание хранилища через defineStore из Pinia, выделение domain-логики (например, useAuthStore, useCartStore), интеграция с API-клиентом.
  4. Работа с внешними API — использование fetch или библиотек вроде axios, инкапсуляция запросов в composables (useApi, useResource), обработка ошибок и состояний загрузки.
  5. Оптимизация сборки — настройка Vite для code splitting, prefetch/preload, генерации sourcemap’ов, tree shaking.

Типичное приложение среднего масштаба (например, внутренняя CRM-система или личный кабинет пользователя) будет включать:

  • Корневой компонент App.vue с навигацией и общей структурой макета.
  • Маршруты, организованные по доменным областям: /profile, /orders, /settings.
  • Хранилища Pinia для сессии, профиля, списка сущностей (заказы, товары).
  • Composables для повторно используемой логики: useDebounce, useLocalStorage, useMediaQuery.
  • Глобальные директивы (например, v-focus, v-tooltip) и миксины (устаревшее, но встречающееся в legacy-коде).
  • Интеграция с системой локализации (vue-i18n) и аналитикой (например, useTrackEvent).

Важно: Vue не навязывает строгой структуры каталогов. Однако сообщество выработало де-факто стандарты:
/src/components — переиспользуемые UI-компоненты (кнопки, карточки),
/src/views — страницы-маршруты,
/src/stores — Pinia-хранилища,
/src/composables — логические модули,
/src/router — конфигурация маршрутов,
/src/assets, /src/styles — статика и глобальные стили.

Такая организация упрощает масштабирование и передачу проекта между разработчиками.

Сравнение Vue с React и Angular

Vue часто сравнивают с React и Angular, но корректное сравнение требует смещения акцента с «кто мощнее» на «как решается та же задача».

По сравнению с React ключевое различие — в уровне абстракции и явности. React — это библиотека для построения UI, где всё, включая маршрутизацию, состояние и побочные эффекты, решается через комбинацию хуков и сторонних библиотек. Vue — фреймворк с официальным стеком, где решения предлагаются «из коробки», но остаются заменяемыми.

React использует JSX — расширение JavaScript для описания UI. Это даёт полную выразительность языка, но требует привыкания и усложняет статическую проверку. Vue использует расширенный HTML с директивами — более привычный для веб-разработчиков с бэкграундом в шаблонных движках (например, Jinja, Handlebars). Оба подхода компилируются в одни и те же render-функции, но синтаксис влияет на когнитивную нагрузку и обучаемость.

Реактивность в React построена на иммутабельности и useState/useReducer: при изменении состояния создаётся новая ссылка, что запускает повторный рендеринг. Vue использует мутабельность и отслеживание доступа: изменения происходят «на месте», а система сама определяет, какие компоненты зависят от изменившихся данных. Это делает Vue более эффективным при работе с большими объектами и глубокими вложенными структурами, но требует осторожности при работе с нереактивными ссылками (например, Object.freeze).

По сравнению с Angular (не AngularJS) Vue избегает принудительной архитектуры. Angular требует использования декораторов (@Component, @Injectable), системы внедрения зависимостей, строгого разделения модулей, обязательного TypeScript. Vue допускает JavaScript, не требует DI, и позволяет начать с одного файла. При этом Vue 3 с Composition API и Pinia приближается к Angular по выразительности управления состоянием, но сохраняет декларативность и отсутствие boilerplate.

Все три технологии способны решать одни и те же задачи: построение SPA, SSR, мобильных приложений (через Capacitor / Ionic), desktop-приложений (через Electron). Выбор определяется контекстом: размером команды, требованиями к типизации, скорости ввода новых разработчиков, существующей инфраструктурой.

Миграция с Vue 2 на Vue 3

Миграция — поэтапный процесс, особенно в крупных проектах. Vue 3 сохраняет обратную совместимость на уровне Options API, но некоторые API устарели или изменены.

Ключевые изменения, требующие внимания:

  • Глобальный API: Vue.component(), Vue.directive(), Vue.mixin() заменены на методы экземпляра приложения (app.component(), app.directive()). Это устраняет глобальное состояние и улучшает изоляцию.
  • v-model для компонентов: в Vue 2 использовался value/input, в Vue 3 — modelValue/update:modelValue. Требуется обновление всех кастомных компонентов форм.
  • Фрагменты: компоненты могут возвращать несколько корневых узлов (без обёртки в <div>), что ломает предположения legacy-кода о единственном root-элементе.
  • this.$refs, this.$el: поведение изменилось при использовании ref в шаблоне с Composition API — теперь ref возвращает сам элемент или компонент, а не объект $refs.
  • Удалены устаревшие API: $set, $delete, keyCode-модификаторы, фильтры (filters).

Инструменты миграции:

  • vue/compat — режим совместимости, позволяющий запускать Vue 2-код в Vue 3 с предупреждениями о deprecated-функциях. Включается через createApp(App).use(createCompatVue()).
  • vue-codemod — набор трансформеров на основе jscodeshift, автоматизирующих замену синтаксиса (например, v-modelv-model с новыми именами событий).
  • @vue-migration-helper — утилита командной строки, сканирующая код и выдающая отчёт о необходимых правках.

Стратегия миграции:

  1. Обновление зависимостей: vue, vue-router, vuex/pinia, @vue/cli-service → соответствующие версии для Vue 3.
  2. Включение vue/compat и запуск приложения — сбор всех предупреждений.
  3. Поэтапная замена компонентов: сначала простые, не имеющие v-model или кастомных директив; затем — сложные, с использованием defineComponent и Composition API.
  4. Замена Vuex на Pinia — необязательна, но рекомендуется, так как Pinia проще, типобезопаснее и не требует мутаций.
  5. Отключение vue/compat после полного перехода.

Важно: миграция — повод провести рефакторинг. Часто legacy-компоненты содержат избыточную логику, которую можно вынести в composables или упростить за счёт новых возможностей (например, v-memo для оптимизации списков).

Безопасность в SPA

Vue, как и любой клиентский фреймворк, не защищает от уязвимостей автоматически — безопасность обеспечивается разработчиком.

XSS (межсайтовый скриптинг) — главная угроза для SPA. Vue автоматически экранирует интерполяции ({{ userContent }}), но использование v-html или динамического innerHTML обходит эту защиту. Правило: никогда не использовать v-html с данными, поступающими от пользователя, если они не прошли строгую санитизацию (например, через DOMPurify).

Content Security Policy (CSP) — механизм, ограничивающий источники исполняемого кода. Vue 3 совместим с CSP без unsafe-eval, в отличие от Vue 2, где компиляция шаблонов на лету требовала unsafe-eval. Для production-сборок с предварительно скомпилированными шаблонами (что делает Vite по умолчанию) CSP может быть настроена строго: script-src 'self', style-src 'self' 'unsafe-inline' (последнее иногда необходимо для scoped-стилей).

Управление аутентификационными токенами — критическая точка. Токены (JWT, session ID) не должны храниться в localStorage — это уязвимо к XSS. Рекомендуется:

  • использовать httpOnly cookies для хранения refresh-токена (недоступны для JavaScript);
  • передавать access-токен только в заголовке Authorization: Bearer ...;
  • ограничивать scope токенов, использовать короткое время жизни;
  • реализовать механизм отзыва (через denylist на сервере).

Vue не предоставляет встроенных средств для этих задач — они решаются на уровне архитектуры backend и клиентского API-клиента (например, axios interceptor для автоматической подстановки токена и обработки 401/403).

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

Производительность Vue-приложений оценивается по метрикам Web Vitals: First Contentful Paint (FCP), Largest Contentful Paint (LCP), Time to Interactive (TTI), Cumulative Layout Shift (CLS). Vue даёт инструменты для улучшения каждой из них.

На уровне компонентов:

  • v-memo — новая директива Vue 3, позволяющая пропустить рендеринг поддерева, если его зависимости не изменились. Аналог React.memo, но с более гибким условием.
  • keep-alive — кэширование активных компонентов при переключении маршрутов (например, вкладки), избегая повторной инициализации.
  • Ленивая загрузка компонентов: defineAsyncComponent(() => import('./HeavyComponent.vue')) — откладывает загрузку кода до момента фактического отображения.
  • Оптимизация v-for: всегда указывать :key, избегать вычислений в шаблоне ({{ item.price * 1.2 }} → вынести в computed), использовать trackBy для сложных ключей.

На уровне данных:

  • Memoization вычисляемых свойств: computed сам по себе мемоизирован, но при работе с массивами/объектами важно возвращать новые ссылки только при реальных изменениях.
  • Дебаунс и троттлинг: useDebounce для поиска, useThrottle для скролла — предотвращают избыточные вызовы.
  • Избегание глубокой реактивности там, где она не нужна: markRaw для больших статических объектов (например, конфигурации), shallowRef для объектов, изменяемых целиком.

Инструменты профилирования:

  • Vue DevTools → Performance tab: замер времени mount/update, выявление «тяжёлых» компонентов.
  • Chrome DevTools → Performance tab: запись полного трейса, включая JS execution, style recalcs, layout, paint.
  • vite-plugin-inspect — анализ сгенерированных модулей, выявление неоптимальных импортов.
  • Lighthouse — аудит accessibility, SEO, производительности в production-сборке.

Оптимизация всегда начинается с измерения: без метрик нельзя судить об эффективности изменений.


Архитектурные паттерны в Vue: от Container/Presentational до Feature-Sliced Design

Архитектура Vue-приложения определяет скорость внесения изменений, тестируемость и устойчивость к регрессиям. Хотя Vue не навязывает конкретную структуру, в сообществе сложились проверенные подходы.

Container/Presentational (Smart/Dumb Components) — паттерн, заимствованный из React-экосистемы, но органично вписывающийся в Vue. Суть: разделение компонентов на две категории.

Container-компоненты отвечают за логику: получение данных из хранилища или API, обработка событий, управление состоянием. Они «знают», что отображать, но не как. Как правило, это страницы (views) или высокоуровневые блоки (DashboardContainer). Они не содержат разметки, кроме обёрток и передачи props.

Presentational-компоненты — чистые UI-блоки: кнопки, карточки, таблицы, формы. Они получают данные и коллбэки через props, ничего не знают о происхождении данных и не вызывают side effects. Такие компоненты максимально переиспользуемы и легко тестируются в изоляции.

Преимущество — чёткое разделение ответственности. Изменение логики (например, замена REST на GraphQL) затрагивает только container; изменение дизайна — только presentational.

Layered Architecture (слоистая архитектура) — масштабируемый подход для крупных систем. Проект делится на вертикальные слои:

  • Presentation Layer — компоненты, директивы, миксины, связанные с отображением.
  • Application Layer — use-case’ы, orchestration: useCreateOrder(), useApproveDocument(). Здесь происходит координация между хранилищем, API и навигацией.
  • Domain Layer — бизнес-логика, не зависящая от фреймворка: валидаторы, сущности (например, Document, WorkflowInstance), правила преобразования.
  • Infrastructure Layer — технические детали: HTTP-клиенты, кэширование, локальное хранилище, интеграции с внешними SDK.

Такая структура обеспечивает независимость бизнес-правил от UI и упрощает миграцию (например, с Vue 3 на Vue 4 или даже на другой фреймворк).

Feature-Sliced Design (FSD) — подход, разработанный в Яндексе и активно используемый в российских компаниях. Основан на горизонтальном разделении по фичам (а не по типам файлов). Каждая фича — отдельный namespace: features/cart, features/profile/edit.

Внутри фичи:

  • ui — presentational-компоненты;
  • model — локальное состояние (часто через ref/reactive, иногда через Pinia-хранилище уровня фичи);
  • lib — утилиты, специфичные для фичи;
  • api — запросы, относящиеся к фиче.

Общесистемные сущности выносятся в shared (например, shared/ui/Button, shared/lib/validators). Преимущество FSD — локализация изменений: при доработке функционала «редактирование профиля» все затронутые файлы находятся в одном каталоге, что ускоряет навигацию и снижает когнитивную нагрузку.

В Vue FSD особенно эффективен при использовании <script setup> и автоматического импорта компонентов (через unplugin-vue-components). Это устраняет необходимость вручную писать import для каждого UI-элемента.


Интеграция с корпоративными системами

Vue часто применяется как frontend-слой для enterprise-платформ, где основная логика сосредоточена в бэкенде. Интеграция требует учёта специфики метаданных, форм, жизненного цикла сущностей.

GraphQL и gRPC — альтернативные протоколы. Vue не имеет встроенной поддержки, но интегрируется через Apollo Client (GraphQL) или @grpc/grpc-js (gRPC-Web). Это оправдано при сложных запросах с вложенными сущностями, где REST требует множества round-trip’ов.


Кастомные директивы и плагины

Vue позволяет расширять базовый функционал без изменения ядра — через директивы и плагины.

Кастомные директивы — это функции, привязанные к DOM-элементу, с доступом к жизненному циклу: created, beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted. Они идеальны для логики, тесно связанной с DOM:

  • v-tooltip — отображение всплывающих подсказок при наведении;
  • v-focus — автоматическая установка фокуса при монтировании;
  • v-permission — условное отображение элемента на основе прав пользователя (например, v-permission="'document.edit'");
  • v-debounce — автоматический debounce для input-полей.

Пример директивы v-permission:

app.directive('permission', {
mounted(el, binding, vnode) {
const { value: requiredPermission } = binding
const userPermissions = store.getters['auth/permissions']
if (!userPermissions.includes(requiredPermission)) {
el.parentNode?.removeChild(el)
}
}
})

Важно: директива не должна содержать бизнес-логику — она лишь применяет правило, полученное извне.

Плагины — механизм глобального расширения. Плагин — это объект с методом install(app: App, options?: any). Внутри install можно:

  • регистрировать компоненты, директивы, глобальные свойства (app.config.globalProperties.$http = axios);
  • внедрять middleware (например, для логирования запросов);
  • инициализировать сторонние библиотеки (Amplitude, Sentry).

Пример плагина для трекинга:

export const TrackingPlugin = {
install(app: App, options: { apiKey: string }) {
const client = initTracking(options.apiKey)
app.config.globalProperties.$track = client.track
app.provide('tracking', client)
}
}

После app.use(TrackingPlugin, { apiKey: '...' }) метод $track доступен во всех компонентах через this.$track (Options API) или inject('tracking') (Composition API).

Плагины позволяют вынести инфраструктурную логику из компонентов и обеспечить единообразие в проекте.


Автоматизация документирования

Для enterprise-проектов документирование - требование. Vue поддерживает генерацию документации на нескольких уровнях.

Vue Docgen API — инструмент, извлекающий метаданные из .vue-файлов: props, emits, slots, description. На его основе строятся:

  • Vue Styleguidist — интерактивная документация компонентов с live-редактором. Поддерживает Markdown-описания, примеры использования.
  • Vuese — генератор документации в формате Markdown или JSON, интегрируемый в CI/CD.

Пример JSDoc-аннотации в компоненте:

<script setup lang="ts">
/**
* Кнопка с поддержкой различных стилей и состояний.
* @param {string} variant - Тип кнопки: 'primary', 'secondary', 'danger'
* @param {boolean} disabled - Блокирует взаимодействие
* @event click - Вызывается при нажатии
*/
defineProps<{
variant?: 'primary' | 'secondary' | 'danger'
disabled?: boolean
}>()
</script>

Storybook — де-факто стандарт для документирования UI-компонентов. Для Vue 3 используется @storybook/vue3. Преимущества:

  • изоляция компонентов от приложения;
  • интерактивные controls для props;
  • тестирование в разных состояниях (loading, error, disabled);
  • интеграция с Chromatic для визуального регрессионного тестирования.

Docusaurus — статический генератор для документации продуктов. Vue может быть использован как фронтенд для Docusaurus (через @docusaurus/preset-classic), а также как источник данных: Markdown-файлы из /docs автоматически превращаются в страницы.

Комбинация Storybook (для разработчиков UI) + Docusaurus (для пользователей и интеграторов) даёт полный цикл документирования.


Поддержка legacy-браузеров и ограничения Vue 3

Vue 3 официально поддерживает только современные браузеры: Chrome ≥87, Firefox ≥78, Safari ≥13.5, Edge ≥88. Internet Explorer 11 и старые версии Edge (на базе EdgeHTML) не поддерживаются — из-за зависимости от Proxy, Set, Map, Promise.

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

  1. Остаться на Vue 2 — стабильная ветка с LTS до конца 2023 года (фактически — поддержка продолжается через community). Vue 2 работает в IE11 при подключении polyfills (core-js, regenerator-runtime).

  2. Использовать Vue 3 в режиме совместимости + polyfills — частично возможно, но:

    • Proxy нельзя заменить polyfill’ом;
    • reactive() не будет работать — только ref();
    • многие библиотеки (Pinia, Vue Router 4) не поддерживают IE11.
  3. Гибридная архитектура: критически важные модули — на Vue 2, новые фичи — на Vue 3 в отдельном micro-frontend’е (через Module Federation или single-spa).

Для сборки под ES5 в Vite требуется:

  • @vitejs/plugin-legacy — генерирует две сборки: modern (ES2020+) и legacy (ES5);
  • core-js и regenerator-runtime в entry point;
  • настройка browserslist в package.json.

Однако даже с полифиллами остаются ограничения:

  • отсутствие v-memo;
  • невозможность использовать Suspense с async setup;
  • снижение производительности из-за overhead polyfills.

Рекомендация: провести аудит аудитории. Если доля IE11 < 1%, экономически целесообразнее показывать баннер с призывом обновить браузер, чем нести издержки поддержки.


Micro-frontends с Vue: изоляция, композиция, совместное использование зависимостей

Micro-frontends (MFE) — архитектурный паттерн, при котором единое пользовательское приложение составляется из независимо разрабатываемых, тестируемых и развёртываемых фронтенд-модулей. Vue поддерживает MFE через несколько подходов, каждый со своими компромиссами.

Webpack Module Federation — наиболее зрелое решение на текущий момент. Основано на динамическом импорте удалённых модулей во время выполнения. В Vite также доступна экспериментальная поддержка через @originjs/vite-plugin-federation.

В конфигурации vite.config.ts хост-приложение объявляет:

plugins: [
federation({
name: 'shell',
remotes: {
userProfile: 'userProfile@http://localhost:3001/assets/remoteEntry.js',
documentFlow: 'documentFlow@http://localhost:3002/assets/remoteEntry.js'
},
shared: ['vue', 'pinia']
})
]

А удалённый модуль — экспортируемые компоненты:

federation({
name: 'userProfile',
filename: 'remoteEntry.js',
exposes: {
'./ProfileWidget': './src/components/ProfileWidget.vue'
},
shared: ['vue']
})

Ключевые аспекты:

  • Изоляция версий Vue — через shared: { vue: { singleton: true, requiredVersion: '^3.4.0' } }. Гарантирует, что в runtime загружается только одна копия ядра, избегая конфликтов.
  • Передача состояния — через props, события или shared-хранилище (например, Pinia-инстанс, переданный через app.provide() в хосте и inject() в удалённом модуле).
  • Совместимость роутинга — Vue Router должен быть инициализирован только в хосте; удалённые модули используют относительные пути или useRouter() без конфигурации.

single-spa — framework-agnostичный оркестратор. Vue-приложение оборачивается в специальный адаптер (single-spa-vue), реализующий контракт: bootstrap, mount, unmount. Позволяет смешивать Vue, React, Angular в одном SPA.

qiankun — китайская библиотека от Ant Group, основанная на sandbox’ах (через Proxy и with-подобные конструкции). Обеспечивает жёсткую изоляцию CSS и глобального состояния, но требует аккуратной настройки CSP.

Антипаттерны MFE:

  • Обмен данными через localStorage или window — нарушает изоляцию и усложняет отладку.
  • Дублирование зависимостей без singleton: true — увеличивает размер бандла и вызывает runtime-ошибки.
  • Слишком мелкое дробление — каждый микросервис должен представлять законченную бизнес-функцию («редактирование профиля», «прохождение согласования»), а не отдельный компонент.

MFE оправданы в условиях:

  • крупных команд с автономными циклами разработки;
  • необходимости постепенной миграции legacy-систем;
  • многоязычных фронтендов (например, часть на Vue, часть — на Angular для интеграции с внутренними библиотеками).

Тестирование в промышленных масштабах: стратегия и инструменты

Тестирование Vue-приложений строится на трёх уровнях, каждый — со своими целями и метриками.

Компонентные тесты (Component Tests) — проверка корректности рендера, реакции на props, событий и состояния. Используется Vue Test Utils + Vitest.

Пример теста:

import { mount } from '@vue/test-utils'
import UserProfile from './UserProfile.vue'

test('отображает имя пользователя', () => {
const wrapper = mount(UserProfile, {
props: { name: 'Тимур' }
})
expect(wrapper.text()).toContain('Тимур')
})

test('вызывает событие при нажатии кнопки', async () => {
const wrapper = mount(UserProfile, { props: { name: 'Тимур' } })
await wrapper.get('button').trigger('click')
expect(wrapper.emitted()).toHaveProperty('edit')
})

Важные практики:

  • Тестировать только публичный интерфейс компонента (props, emits, slots), а не внутренние переменные.
  • Использовать global.mocks для замены $t, $route и других инжекций.
  • Измерять coverage: vitest --coverage, нацеливаться на ≥80% для критических компонентов.

Интеграционные тесты — проверка взаимодействия нескольких компонентов и хранилищ. Например, корректность работы формы с Pinia-хранилищем:

test('сохранение профиля обновляет состояние', async () => {
const pinia = createPinia()
const wrapper = mount(ProfileForm, {
global: { plugins: [pinia] }
})

await wrapper.find('input[name="email"]').setValue('timur@example.com')
await wrapper.find('form').trigger('submit')

const store = useProfileStore()
expect(store.email).toBe('timur@example.com')
})

E2E-тесты (End-to-End) — сценарии, имитирующие действия пользователя в браузере. Используется Cypress или Playwright.

Пример на Playwright:

test('пользователь может пройти авторизацию и попасть в личный кабинет', async ({ page }) => {
await page.goto('/login')
await page.fill('#login', 'timur')
await page.fill('#password', 'secret')
await page.click('button[type="submit"]')
await expect(page).toHaveURL('/dashboard')
await expect(page.locator('h1')).toHaveText('Добро пожаловать, Тимур')
})

Критерии выбора:

  • Cypress — быстрее запускается, лучше отладка, но ограничен одним браузером (Chromium).
  • Playwright — поддержка Chromium, Firefox, WebKit, изоляция контекстов, эмуляция мобильных устройств.

Для CI рекомендуется:

  • Запуск компонентных тестов на каждом PR.
  • E2E — только для main и релизных веток из-за длительности.
  • Параллельный запуск с шардированием (--shard=1/4 в Playwright).

CI/CD для Vue-приложений

Типичный pipeline для Vue-проекта включает этапы:

  1. Lint и type-checkeslint, typescript --noEmit. Выполняются быстро, блокируют сборку при ошибках.
  2. Сборка production-версииvite build. Генерирует оптимизированные asset’ы в dist/.
  3. Запуск тестов — компонентные (vitest), интеграционные, E2E (частично).
  4. Анализ bundle’аrollup-plugin-visualizer или source-map-explorer, контроль размера критических чанков.
  5. Деплой — static hosting (Vercel, Netlify, S3 + CloudFront) или SSR-сервер (Node.js на PM2/Kubernetes).

Preview-сборки — важный элемент MFE и командной работы. При открытии PR автоматически собирается и деплоится изолированная версия приложения по уникальному URL (например, pr-123.app.example.com). Реализуется через:

  • GitHub Actions + Vercel CLI;
  • GitLab Pages с динамическими namespace’ами;
  • собственный хостинг с wildcard SSL.

Канареечные релизы — постепенный выпуск новой версии части пользователей. Требует:

  • поддержки feature flags (через @unleash/proxy-client-vue);
  • мониторинга ошибок и метрик в реальном времени;
  • автоматического отката при превышении порога ошибок (например, >0.5% 5xx).

Для фронтенда канареечность достигается через:

  • A/B-тестирование на CDN (Cloudflare Workers, Akamai);
  • динамическую загрузку чанков с разных хостов (например, v1.assets.com и v2.assets.com);
  • feature flags в конфигурации, передаваемой с бэкенда.

Мониторинг и аналитика

Vue-приложения требуют трёх уровней наблюдаемости:

1. Отслеживание ошибок — через Sentry или Rollbar. Интеграция:

import * as Sentry from '@sentry/vue'

Sentry.init({
app,
dsn: 'https://...',
integrations: [new Sentry.BrowserTracing()],
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0
})

Sentry автоматически ловит:

  • исключения в обработчиках событий;
  • ошибки в жизненном цикле (например, beforeMount);
  • необработанные promise-ошибки.

Дополнительно можно отправлять breadcrumbs — контекст перед ошибкой (последние действия пользователя, состояние маршрута, значение полей формы).

2. Производительность и метрики — через OpenTelemetry или Google Analytics 4 (GA4).

OpenTelemetry для фронтенда:

  • замер FCP, LCP, CLS через Web Vitals API;
  • трассировка запросов к API (включая заголовки traceparent);
  • кастомные spans для длительных операций (например, парсинг большого CSV).

GA4 фокусируется на поведении:

  • события page_view, click, form_submit;
  • параметры: content_type, item_id, value;
  • аудиторные сегменты (пользователи, которые дошли до шага 3 в воронке).

3. APM (Application Performance Monitoring) — Datadog RUM, New Relic Browser. Объединяют ошибки, производительность, сессии и трассировки в едином интерфейсе. Позволяют:

  • смотреть replay’ы проблемных сессий;
  • коррелировать фронтенд-ошибки с backend-логами по trace ID;
  • строить heatmaps кликов и скролла.

Важно: сбор данных должен быть конфигурируемым и соответствовать GDPR/152-ФЗ. Для этого:

  • запрос согласия перед инициализацией;
  • анонимизация IP;
  • возможность отключения в настройках.

RFC, текущие разработки, долгосрочные планы

Разработка Vue ведётся прозрачно через систему RFC (Request for Comments) на GitHub. Каждое крупное изменение проходит стадии: proposal → discussion → implementation. Актуальные направления:

1. Compiler Optimizations (RFC #512) — переход от runtime-проверок к compile-time. Например:

  • автоматическое определение статических узлов (hoistStatic);
  • исключение неиспользуемых веток v-if на этапе сборки;
  • оптимизация v-for с известным размером массива.

Цель — уменьшение размера runtime-библиотеки и повышение скорости рендеринга.

2. Template Reactivity Scope (RFC #524) — реактивность на уровне шаблона. Вместо глобального отслеживания всех свойств компонента, компилятор будет генерировать только необходимые зависимости, основываясь на анализе шаблона. Это снизит overhead для компонентов с большим data, но малым использованием.

3. Better TypeScript DX — улучшение вывода типов для defineProps, defineEmits, SFC. В частности:

  • поддержка generic-компонентов в шаблоне;
  • строгая проверка слотов и их props;
  • интеграция с vue-tsc --noEmit как стандартом для проверки.

4. Suspense и Async Setup Stabilization — выход из экспериментального статуса. Планируется:

  • поддержка Suspense в SSR без дополнительных хуков;
  • улучшенная обработка ошибок в async-компонентах;
  • интеграция с useAsyncData в Nuxt.

5. Vue 3.5 и 3.6 — фокус на стабильность, исправление edge-case’ов, улучшение совместимости с инструментами (Volar, Vitest), расширение официальной документации примерами для enterprise-сценариев.

Долгосрочная цель — сохранение баланса между инновациями и стабильностью. Vue не стремится быть «самым быстрым» или «самым функциональным», но остаётся ориентированным на developer experience, предсказуемость и постепенную адаптацию.