Когда одного фреймворка недостаточно
Вы выбрали React. Команда пишет на нём уже несколько лет, выстроена компонентная архитектура, налажены процессы. Но вот задача, где React оказывается не на своём месте: нужно быстро встроить интерактивный виджет на страницу со сложной legacy-разметкой, которую нельзя трогать. Или наоборот — у вас продукт на Vue, а заказчик принёс готовый React-компонент. Переписывать? Долго и дорого. Игнорировать? Потерять конкурентное преимущество.
Оба фреймворка входят в число самых используемых инструментов фронтенда, и всё чаще команды сталкиваются с ситуацией, когда в рамках одного проекта возникает необходимость использовать и React, и Vue.js одновременно. Это не вопрос «кто лучше» — это вопрос гибкости и скорости разработки.
В этой статье мы разберём, как совмещать React и Vue.js в одном приложении. Вы узнаете о трёх подходах к их совместному использованию, поймёте, в каких сценариях это действительно выгодно, и получите пошаговую инструкцию по интеграции. На выходе — готовое понимание, как не переписывать код, а заставить оба фреймворка работать вместе.
Почему возникает необходимость в комбинации React и Vue
Представьте: вы разрабатываете корпоративное веб-приложение. Основная часть написана на React, но отдел маркетинга принёс готовый Vue-компонент для A/B-тестирования целевых страниц. Переписывать его на React — две недели работы и риск внести ошибки. В то же время, бизнес не может ждать — старт кампании запланирован на понедельник. Знакомая ситуация?
В большинстве случаев проблема упирается не в технические ограничения, а в скорость поставки. Когда один отдел использует Vue благодаря его простоте для прототипирования, а другой — React из-за зрелой экосистемы, конфликт технологий неизбежен. Многие команды в enterprise-сегменте уже имеют проекты, использующие более одного фреймворка одновременно.
Последствия выбора «или-или»:
Потеря времени на переписывание готовых решений.
Усложнение поддержки за счёт дублирования логики.
Демотивация разработчиков из-за бесконечного рефакторинга.
Практический совет: не бойтесь сосуществования фреймворков. Гораздо опаснее — потратить ресурсы на миграцию, когда этого можно избежать. Рассмотрите возможность интеграции до того, как приметесь за переписывание.
Три подхода к совместному использованию React и Vue
Когда вы решили, что комбинирование необходимо, встаёт вопрос: как именно это сделать технически? Существует три основных стратегии. У каждой есть свои сильные и слабые стороны.
Подход 1: Микрофронтенды с изоляцией
Каждый фреймворк живёт в собственном независимом модуле (micro-frontend). Взаимодействие происходит через единую шину событий или URL. React-часть отвечает за навигацию и дашборды, Vue — за редактор контента или виджеты. Плюсы: полная изоляция зависимостей, возможность независимого деплоя. Минусы: сложность настройки общей обвязки (роутинг, аутентификация), дублирование базовых библиотек (например, axios), что увеличивает размер бандла. Для реализации часто используют Module Federation от Webpack 5 или Single SPA — эти инструменты позволяют организовать общий хост и удалённое подключение модулей.
Подход 2: Встраивание через Web Components (Custom Elements)
Вы оборачиваете компонент на Vue в нативный Web Component и используете его внутри React-приложения как обычный HTML-элемент. Плюсы: технология стандартизирована, работает в любом фреймворке, не требует дополнительной разметки. Минусы: ограниченная передача сложных пропсов (только строки и объекты), сложности с синхронизацией состояний, потенциальные проблемы с Shadow DOM и стилями.
Подход 3: Рендеринг внутри контейнера (IFrame)
Это наиболее простой, но тяжёлый метод. Vue-приложение загружается в IFrame, React-приложение — в основном окне. Плюсы: максимальная изоляция, отсутствие конфликтов библиотек. Минусы: производительность (отдельный рендеринг, потребление памяти), ограниченное взаимодействие между окнами (только через postMessage), проблемы с сессиями и куками.
На практике подход с Web Components выбирают чаще других: он обеспечивает наилучший баланс между изоляцией и простотой интеграции без необходимости строить отдельную инфраструктуру.
Почему Web Components — оптимальный выбор
Из трёх вариантов именно Web Components обеспечивает наилучший баланс между изоляцией и простотой интеграции. Вы не строите отдельную инфраструктуру, как в микрофронтендах, и не жертвуете производительностью, как в IFrame. React-приложение «не знает», что внутри — Vue, Svelte или простой HTML.
Кроме того, этот подход не требует переписывания логики на «общий язык». Вы сохраняете нативную среду каждого фреймворка: React работает со своим виртуальным DOM, Vue — со своим реактивным движком. Это критически важно, если один из них использует устаревшую версию или специфическую библиотеку, которая не переносится на другой стек.
Эту задачу можно автоматизировать с помощью компонентного подхода: создайте единожды Vue-виджет как Custom Element и используйте его в любом React-проекте. Время на интеграцию сокращается с нескольких дней до нескольких часов. Для этого потребуется лишь обёртка из стандартных API — customElements.define().
Пошаговая интеграция Vue-компонента в React
Рассмотрим конкретный пример: у вас есть React-приложение на Create React App, и вы хотите встроить в него готовый Vue-компонент — кастомный календарь с фильтрами.
Создайте Vue-компонент в отдельном файле, используя стандартный Composition API или Options API. Например, простой календарь с пропсами
startDateиfilter.Установите пакет для рендеринга Vue в Custom Element:
npm install @vue/web-component-wrapper(или используйте встроенную функциюdefineCustomElementв Vue 3).Оборачиваем компонент:
import { defineCustomElement } from '@vue/web-component-wrapper' import VueCalendar from './VueCalendar.vue' const CalendarElement = defineCustomElement(VueCalendar) customElements.define('vue-calendar', CalendarElement)Соберите Vue-компонент в отдельный бандл. Важно: не включайте его в основной React-бандл. Используйте
viteилиwebpackс отдельной точкой входа, чтобы Vue и его зависимости не попали в общую сборку.Подключите скрипт с готовым Web Component в HTML-файле или динамически в React-коде.
Используйте в React:
<vue-calendar start-date="2024-01-01" filter='{"type":"month"}' />. React будет воспринимать это как обычный DOM-элемент. Для передачи объектов используйте JSON-строку в атрибутах, а внутри Vue-компонента парсите обратно. Для реактивного обновления данных используйте атрибуты — каждое изменение атрибута запускаетattributeChangedCallback.
Важный нюанс: если передаёте объекты или массивы, конвертируйте их в JSON-строку в атрибутах, а внутри Vue-компонента парсите обратно. Для реактивного обновления данных используйте атрибуты — каждое изменение атрибута запускает attributeChangedCallback.
Типичные ошибки при комбинировании React и Vue
Даже при правильном подходе разработчики часто допускают одни и те же ошибки. Вот пять наиболее частых:
Ошибка 1: отсутствие изоляции стилей. Если не использовать Shadow DOM, стили из Vue могут переопределить стили React и наоборот. Как правильно: при создании Custom Element укажите
{ shadowRoot: true }. Это гарантирует, что стили виджета не выйдут за его пределы. Однако помните, что Shadow DOM может усложнить доступность (a11y) — используйтеpartиexportpartsдля стилизации извне.Ошибка 2: попытка передать функции как пропсы. Custom Elements не поддерживают передачу функций через атрибуты. Как правильно: используйте события — в Vue генерируйте событие, а в React подписывайтесь на него через
addEventListenerили атрибутon-{event}.Ошибка 3: дублирование зависимостей. Если вы включили Vue в основной бандл React-приложения, производительность упадёт — загрузятся обе библиотеки сразу. Как правильно: выделите Vue-виджет в отдельный чанк (
lazy loading), чтобы он загружался только при необходимости.Ошибка 4: забывают про SSR. Если ваше React-приложение использует серверный рендеринг (Next.js), Web Components не будут работать на сервере. Как правильно: используйте динамический импорт с проверкой
typeof window !== 'undefined'или оборачивайте компонент вClientOnly-обёртку. Для гидратации можно использовать@lit-labs/ssrили аналогичные решения.Ошибка 5: игнорирование управления состоянием. Если Vue-виджет должен реагировать на изменения в React-сторе (Redux, Zustand), а вы не синхронизируете их, появляются баги. Как правильно: передавайте ключевые данные через атрибуты и слушайте события для обратной связи. Для сложной синхронизации используйте простой EventBus или общий стейт-менеджер (например, Nano Stores).
Заключение
Комбинирование React и Vue.js — это не сценарий «аварийного выхода», а зрелый архитектурный подход. Он позволяет сэкономить ресурсы, сохранить инвестиции в существующий код и быстрее доставлять новые функции. Web Components — надёжный и стандартизированный способ объединить разные фреймворки без боли переписывания.
Попробуйте применить этот подход на ближайшем спринте: выберите один изолированный компонент (виджет, календарь, форму) и оберните его в Custom Element. После этого вы сможете использовать его в параллельном проекте на другом фреймворке без единой строки изменений. Для оценки успешности интеграции измерьте размер бандла и время загрузки до и после.
Готовы взять ситуацию под контроль? Изучите документацию React по интеграции с другими библиотеками или начните с небольшого эксперимента — создайте отдельный репозиторий и попробуйте встроить Vue-виджет в React. У вашей команды точно есть что-то, что можно объединить.
