Сравнение с другими фреймворками

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

Мы очень постараемся не быть предвзятыми. Будучи членами основной команды разработки Vue, мы, разумеется, сами его очень любим. На наш взгляд, с некоторыми задачами Vue справляется лучше, чем какой-либо другой существующий фреймворк. Если бы мы не верили в это, мы бы наверное и не работали над этим проектом, верно? И тем не менее, нам бы хотелось быть предельно честными и точными в оценках. В тех случаях, когда альтернативные библиотеки имеют существенные преимущества, как например обширнейшая экосистема альтернативных рендереров React’а или поддержка браузеров вплоть до IE6 Knockout’ом, мы постараемся не забыть о них упомянуть.

Кроме того, мы очень высоко ценим вашу помощь в деле поддержания актуальности этого документа, потому что мир JavaScript развивается стремительно! Если вы заметите какую-либо неточность или ошибку — пожалуйста, дайте нам знать, открыв issue на Github.

React

React и Vue во многом похожи. Они оба:

Из-за столь похожих ниш, мы уделили сравнению этих фреймворков больше всего времени. Нашей целью было не только удостовериться в технической точности, но также и сохранить баланс. Мы указываем, где React превосходит Vue, например — в богатстве экосистемы и изобилии доступных пользовательских рендереров.

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

Помощь React-сообщества была неоценима в деле достижения этого баланса. Особо хотелось бы поблагодарить Даниила Абрамова из команды разработки React. Он был крайне щедр на время и опыт, помогая нам довести этот документ до состояния, когда обе стороны остались довольны финальным результатом.

Сравнение быстродействия

В каждом из реалистичных сценариев, в котором мы проводили тесты, Vue существенно превзошёл React по быстродействию. Если ваши брови сейчас приподнялись, читайте дальше. Мы расскажем, почему (и даже покажем бенчмарк, разработанный вместе с командой React).

Быстродействие при рендеринге

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

  1. Минимизировать необходимое количество изменений в DOM. Как React, так и Vue используют для этих целей Virtual DOM — и примерно с равным успехом.
  2. Привнести как можно меньше дополнительных накладных расходов в виде JavaScript-операций “поверх” манипуляций с DOM. В этой области Vue и React отличаются.

Упомянутые накладные расходы напрямую связаны с механизмами, используемыми для определения операций, необходимых для выполнения с DOM. Как Vue, так и React используют Virtual DOM, но реализация Virtual DOM, используемая во Vue (форк snabbdom) значительно более легковесна, и потому привносит меньше накладных расходов по сравнению с используемой в React.

В React, условно говоря, дополнительная трудоёмкость рендеринга элемента равна 1, а для компонента — 2. Для Vue эти цифры будут ближе к 0.1 и 4 соответственно. Это значит, что в типичных приложениях, где простых элементов DOM куда больше, чем компонентов, Vue будет существенно обгонять React. В экстремальных же случаях, как например при использовании компонента для каждого HTML-элемента, Vue обычно будет медленнее. Но это ещё не всё.

И Vue, и React позволяют использовать функциональные компоненты, не имеющие ни собственного состояния, ни экземпляра — и потому требующие меньших вычислительных затрат. При использовании таких компонентов в критичных по быстродействию ситуациях, Vue вновь оказывается быстрее. Для демонстрации этого, мы создали простой бенчмарк, который 100 раз подряд рендерит 10,000 элементов списка. Мы предлагаем вам самим его запустить. Результаты отличаются в зависимости от используемого железа, браузера — и даже просто от запуска к запуску, в силу природы JavaScript-движков.

Впрочем, если вам лень этим заниматься, вот цифры, полученные при запуске этого теста в Chrome 52 на MacBook Air 2014. Таблица обобщает результаты 20 запусков:

Vue React
Самое быстрое 23мс 63мс
Медиана 42мс 81мс
Среднее 51мс 94мс
95-й перцентиль 73мс 164мс
Самое медленное 343мс 453мс

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

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

Это значит, что обновления в приложениях без специально проведённой оптимизации Vue будет показывать значительно лучшую производительность. В действительности, даже полностью оптимизированные React-приложения обычно оказываются медленнее, чем приложения Vue “из коробки”.

Производительность при разработке

Разумеется, производительность в production важнее всего, поскольку именно она влияет на качество опыта конечных пользователей при взаимодействии с приложением. Но и во время разработки быстродействие используемого фреймворка имеет немалое значение — она определяет качество опыта разработчика.

И Vue, и React в режиме разработки остаются довольно шустрыми для большей части приложений. Однако, при прототипировании высокопроизводительных визуализаций данных и анимаций, мы обнаружили сценарии, в которых производительность Vue в режиме разработки падала до 10 кадров в секунду. React в этих же сценариях показал результаты на уровне 1 кадра в секунду.

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

HTML & CSS

В React, абсолютно всё — это JavaScript. Звучит это заявление очень просто и элегантно — до тех пор, пока не начнёшь копать глубже. Неприятное свойство реальности заключается в том, что изобретая заново HTML и CSS внутри JavaScript можно испытать немалые страдания. Во Vue мы, напротив, постарались задействовать существующие веб-технологии. Чтобы показать вам, что из этого вышло, мы рассмотрим несколько примеров.

JSX vs Шаблоны

В React, все компоненты описывают свой UI посредством render-функций, используя JSX — декларативный XML-подобный синтаксис, работающий внутри JavaScript. Вот пример, одобренный сообществом React:

render () {
let { items } = this.props
let children
if (items.length > 0) {
children = (
<ul>
{items.map(item =>
<li key={item.id}>{item.name}</li>
)}
</ul>
)
} else {
children = <p>Ничего не найдено.</p>
}
return (
<div className='list-container'>
{children}
</div>
)
}

Render-функции, использующие JSX, имеют определённые преимущества:

Во Vue тоже есть render-функции, и даже поддержка JSX, так как иногда эти возможности действительно нужны. Тем не менее, в качестве более простой альтернативы мы предлагаем большую часть времени использовать шаблоны:

<template>
<div class="list-container">
<ul v-if="items.length">
<li v-for="item in items">
{{ item.name }}
</li>
</ul>
<p v-else>Ничего не найдено.</p>
</div>
</template>

Вот некоторые преимущества этого подхода:

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

Ещё одно преимущество — возможность использования в шаблонах препроцессоров, таких как Pug (экс-Jade):

div.list-container
ul(v-if="items.length")
li(v-for="item in items") {{ item.name }}
p(v-else) Ничего не найдено.

Модульный (компонентный) CSS

За исключением случаев разделения компонентов на несколько файлов (например, посредством CSS-модулей), для ограничения области видимости CSS в React обычно используется подход CSS-in-JS. В этой области существует множество соревнующихся решений, каждое с собственными недостатками. Общими проблемами являются такие вопросы как: hover states, media queries, псевдоселекторы — и эти вопросы зачастую либо требуют использования дополнительных “тяжёлых” зависимостей для переизобретения уже существующего в CSS функционала, либо вовсе не работают. Кроме того, без специального внимания к оптимизации, CSS-in-JS может нетривиально повлиять на производительность. Что ещё важнее, использование этих инструментов в любом случае существенно отличается от привычного опыта написания обыкновенного CSS.

Vue же позволяет напрямую использовать CSS в однофайловых компонентах:

<style scoped>
@media (min-width: 250px) {
.list-container:hover {
background: orange;
}
}
</style>

Опциональный атрибут scoped автоматически ограничивает область видимости CSS текущим компонентом, добавляя элементам уникальные атрибуты (такие как data-v-1-21e5b78), и компилируя .list-container:hover во что-нибудь вроде .list-container[data-v-1-21e5b78]:hover.

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

Наконец, как и с HTML, у вас есть возможность использования любых препроцессоров (или постпроцессоров) на ваш вкус. Это позволяет применять централизованные операции, такие как управление цветами, на этапе сборки. При этом нет необходимости импортировать специализированные JavaScript-библиотеки, увеличивающие как размер результирующей сборки, так и сложность вашего приложения.

Масштабирование

Масштабирование вверх

Для крупных приложений, как Vue так и React предоставляют надёжные решения для роутинга. Сообщество React также породило весьма инновационные решения в области управления состоянием приложения (см. Flux/Redux). Эти подходы, и даже сам Redux легко интегрируются в приложения на Vue. В действительности, Vue сделал следующий шаг, создав Vuex — вдохновлённую Elm реализацию паттерна управления состоянием приложения. Vuex глубоко интегрирован с Vue, что, на наш взгляд, изрядно облегчает жизнь разработчикам.

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

Наконец, у Vue есть инструменты командной строки для генерации проектов, упрощающие создание новых проектов с использованием подходящей системы сборки, включая Webpack, Browserify, или даже вовсе без таковой. В сообществе React также существуют наработки в этом направлении — например, create-react-app, но на данный момент функционал этого решения имеет ряд ограничений:

Важно заметить, что многие из этих ограничений — следствия сознательно принятых решений команды create-react-app, и в них есть и свои плюсы. Например, коль скоро ваш проект не требует пользовательской настройки процесса сборки, её можно будет обновлять как зависимость. Прочитать больше об этом подходе можно здесь.

Масштабирование вниз

React известен своей довольно крутой кривой изучения. До того момента, когда новичок сможет что-то написать, ему придётся узнать о JSX, а вероятно — и о ES2015+, поскольку многие примеры используют синтаксис ES2015-классов. Кроме того придётся разобраться с системами сборки, поскольку, хотя технически и существует возможность использовать Babel самостоятельно для live-компиляции кода, для production этот подход в любом случае не годится.

Vue масштабируется вверх ничуть не хуже (если не лучше), чем React, и в то же время его можно масштабировать и вниз — вплоть до варианта использования вместе с jQuery. Именно так — в простейшем случае достаточно просто добавить тег скрипта на HMTL-страницу.

<script src="https://unpkg.com/vue/dist/vue.js"></script>

Начиная с этого момента можно писать код на Vue, и даже использовать production-версию, не мучаясь угрызениями совести и волнениями насчёт производительности.

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

Нативный рендеринг

React Native позволяет писать нативные приложения для iOS и Android, используя ту же самую модель компонент React’а. Это — прекрасно, так как позволяет разработчикам применить знание одного и того же фреймворка на различных платформах. В этой области, Vue официально поддерживает проект Weex — кросс-платформенный UI-фреймворк, разрабатываемый Alibaba Group и использующий Vue в качестве основного JavaScript-фреймворка. Это значит, что с Weex вы можете использовать тот же синтаксис Vue для создания нативных элементов iOS и Android!

На данный момент Weex всё ещё находится в активной фазе разработки, и ещё не столь матёр и проверен опытом, как React Native. Однако, его разработка мотивируется реальными требованиями крупнейшего бизнеса электронной коммерции в мире. Команда разработки Vue также активно взаимодействует с разработчиками Weex, гарантируя отсутствие неожиданностей для Vue-разработчиков.

Сравнение с MobX

MobX стал довольно популярным в сообществе React. Он использует почти идентичную Vue систему реактивности. В некотором смысле, связку React + MobX можно считать несколько более многословным вариантом Vue, так что если вы используете её, и она вам нравится, переход на Vue может оказаться следующим логичным шагом.

Angular 1

Некоторые части синтаксиса Vue выглядят очень похоже на синтаксис Angular (например, сравните v-if и ng-if). Это — не случайность: многие идеи, лежащие в основе Angular мы считаем верными, и вдохновлялись ими на ранних этапах разработки Vue. Впрочем, в Angular немало и болезненных проблем, и в этих областях мы постарались добиться значительных улучшений.

Сложность

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

Гибкость и модульность

Angular имеет жёсткое мнение насчёт структуры вашего приложения, в то время как Vue проявляет гибкость и является более модульным решением. Хотя это и делает Vue пригодным для большего разнообразия проектов, мы понимаем и то, что когда решения уже приняты за тебя, можно сразу начать программировать, и в этом есть свои преимущества.

По этой причине мы предоставляем webpack template, позволяющий начать работу уже в течении нескольких минут, давая при этом доступ к таким продвинутым возможностям, как горячая замена модулей, линтинг, извлечение CSS и т.д..

Связывание данных

Angular использует двунаправленное связывание данных между областями видимости, в то время как Vue концентрируется на однонаправленном потоке данных между компонентами. Это позволяет облегчить понимание потока данных в нетривиальных приложениях.

Директивы и компоненты

Vue чётче разделяет директивы и компоненты. Директивы предназначены только для инкапсуляции низкоуровневых манипуляций с DOM, в то время как компоненты являют собой полноценные автономные объекты, со своей собственной логикой данных и представления. В Angular эти две концепции в значительной мере смешаны.

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

Vue производительнее Angular. Кроме того, из-за отсутствия dirty-checking, оптимизировать Vue-приложения намного-намного проще. Angular 1 замедляется при увеличении количества наблюдателей, поскольку каждый раз при изменении чего-либо в области видимости все эти наблюдатели должны быть перезапущены. Кроме того, цикл может повториться несколько раз перед стабилизацией, поскольку реакция наблюдателей может спровоцировать следующее обновление. Пользователям Angular нередко приходится прибегать к весьма эзотерическим техникам для обхода этих трудностей, а в некоторых случаях оптимизация и вовсе становится невозможной.

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

Любопытно, что этот подход делает Vue во многом похожим на Angular 2.

Angular 2

Мы выделяем отдельную секцию для Angular 2, поскольку по сути он является совершенно новым фреймворком. Например, теперь он содержит полноценную компонентную систему; кроме того, многие детали имплементации были полностью переписаны, а API очень существенно изменился.

TypeScript

В то время как Angular мог быть использован для небольших приложений, Angular 2 переносит акцент в область крупных enterprise-приложений. Отчасти по этой причине, он почти требует использования TypeScript, что может быть весьма полезно для разработчиков, предпочитающих безопасную типизацию, привычную по языкам вроде Java и C#.

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

Размер и быстродействие

В смысле производительности, оба фреймворка весьма быстры, и пока нет достаточных данных из реального мира чтобы вынести окончательный вердикт. Но если вы всё же хотите цифр, похоже что Vue 2.0 всё-таки обгоняет Angular 2, по крайней мере если верить этому стороннему исследованию производительности.

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

Гибкость

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

Кривая обучения

Всё что необходимо для начала работы с Vue — это знакомство с HTML и обыкновенным (ES5) JavaScript’ом. С этими базовыми навыками вы уже можете начать строить нетривиальные приложения после менее чем однодневного прочтения руководства.

Кривая обучения Angular 2 значительно круче. Даже без учёта TypeScript, их руководство по быстрому старту начинает с приложения, использующего ES2015 JavaScript и NPM с 18 зависимостями, 4 файлами и более чем 3,000 слов объяснений — просто для “Hello World”. Не будет преувеличением сказать, что Hello World в исполнении Vue — немного попроще. Возможно по этой причине мы даже не посвящаем ему отдельной страницы в нашем руководстве.

Ember

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

Учитывая вышесказанное, вероятно будет разумнее сравнивать ядро Vue и слои шаблонизации и объектной модели Ember:

Knockout

Knockout был пионером MVVM-подхода и отслеживания изменений в данных. Его система реактивности очень похожа на используемую Vue. Список поддерживаемых браузеров — впечатляет, особенно с учётом всех немалых возможностей фреймворка, доступных даже в IE6! Vue же поддерживает только IE9+.

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

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

Polymer

Polymer — это ещё один проект, спонсируемый Google. В действительности, он тоже послужил источником вдохновения для Vue. Компоненты Vue можно приблизительно сравнивать с пользовательскими элементами Polymer. Стиль разработки с использованием обоих фреймворков довольно похож. Самая существенная разница состоит в том, что Polymer базируется на последних возможностях Web Components и требует для работы использования весьма нетривиальных полифиллов (с потерей быстродействия в браузерах без нативной поддержки эти возможностей). Vue, напротив, без каких-либо зависимостей или полифиллов работает во всех браузерах, начиная с IE9.

В Polymer 1.0, разработчики существенно ограничили систему связывания данных для улучшения производительности. Например, единственными поддерживаемыми в шаблонах Polymer выражениями являются булево отрицание и одиночные вызовы методов. Реализация вычисляемых свойств — тоже не очень гибкая.

Пользовательские элементы Polymer пишутся в HTML-файлах, что ограничивает авторов использованием обыкновенного JavaScript/CSS (и возможностей языка, поддерживаемых браузерами на данный момент). Vue же позволяет использовать в однофайловых компонентах какие угодно пре- и построцессоры, включая, разумеется, и ES2015+.

При работе в production-окружении, Polymer рекомендует загружать всё “на лету” при помощи HTML Import’ов, что подразумевает как имплементацию этой технологии браузерами, так и поддержку HTTP/2 и сервером, и клиентом. Не для всякой целевой аудитории и не для всякого окружения это может быть выполнимо. В таких случаях предполагается использовать специальный инструмент под названием Vulcanizer, объединяющий элементы Polymer. Vue позволяет комбинировать возможности асинхронной загрузки компонентов c функциями по разделению кода Webpack’а, организуя “ленивую” загрузку частей приложения. Таким образом мы сохраняем совместимость со старыми браузерами, не теряя производительности на этапе загрузки приложения.

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

Riot

Riot 2.0 предлагает похожую модель разработки, основывающуюся на компонентах (в Riot называемых “тегами”), с минималистичным и прекрасно организованным API. Вероятно, Riot и Vue во многом основаны на схожих философских подходах. Однако, несмотря на немного больший размер по сравнению с Riot, Vue имеет некоторые существенные преимущества: