Вступление



Данный пост — это логическое продолжение моего поста/статьи — Как я перестал любить Angular / How I stopped loving Angular.
Рекомендуется к ознакомлению перед прочтением.


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


Краткий рекап предыдущего поста:


Вот краткий список основных проблем, беспокоивших меня в Angular на момент написания предыдущей статьи:


  1. Ужасный роутер
  2. Тяжеловесное и практические бесполезное Dependency Injection (см. ниже)
  3. Крайне спорная система модулей (не используемая ни в одном другом фреймворке)
  4. Множество лишних и мало полезных абстракций, странный API-design
  5. Observable как часть фреймворка
    ...

DI


Сразу следует оговориться насчет Dependency Injection: после перехода на Vue, все-таки стоит отметить, что в Angular более удобно мокировать внешние зависимости в юнит тестах.


Это полностью зависит от кодовой базы и внутренних best-practice, но нередко во Vue мокировать что-то в тестах получается несколько сложнее, нежели в Angular (пример будет ниже).


Однако я не считаю это серьезным основанием для применения столь чуждого JavaScript'у паттерна на фронт-энде.


Почему не про реакт


И еще одна небольшая оговорка, касательно того, почему был выбран именно Vue, а не React.
Дисклеймер: все пункты ниже ОЧЕНЬ субъективны (поэтому не следует воспринимать их как критику, а лишь как личный взгляд):


  1. Реактивность во Vue просто работает, причем сразу и асинхронно: нет нужды заморачиваться с иммутабельностью и чистыми функциями
    (концепция иммутабельности очень крутая, но зачастую крайне многословная — почти всегда это долго и дорого)
  2. JSX плох сразу по нескольким причинам:
    • Медленная миграция HTML разметки в код приложения — особенно здесь страдают дизайнеры, которым приходится привлекать разработчика иногда для довольно тривиальных вещей
    • Постоянно, даже без особой нужды, приходится дробить все на мелкие компоненты, что отнимает время VS шаблонизация в Angular/Vue – компоненты выносятся по необходимости в любой момент
    • В моей памяти еще свежи воспоминания о том, что кондишeны = боль
  3. Формы адовые – про это позже
  4. сreate-react-app на мой взгляд, на сегодняшний день, является самым мало-функциональным CLI из всех наиболее популярных фреймворков, уж для React давно стоит создать гораздо более мощную тулзу
  5. У нашей команды был довольно богатый опыт работы с Angular — по ряду схожих факторов войти во Vue им было гораздо проще

Отличия и впечатления после Angular


Немного про основные отличия и впечатления которые я отметил для себя при переходе на Vue.


Документация


Первое с чем вы столкнетесь выбрав UI фреймворк, это, конечно же, документация.


Не буду повторно разбирать документацию Angular с ее


Banana in a box

скажу лишь, что во Vue она значительно более простая и доходчивая.


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


Также стоит отметить, что доки написаны на 6 языках, хотя хватило бы и английского (считаю, что сейчас любой разработчик должен знать English хотя бы на уровне чтения).


CLI


Из моей предыдущей статьи вы могли понять, что раньше я думал что Angular CLI самое лучшее, но, как выяснилось:


  1. Его порой крайне сложно кастомизировать
  2. Angular и CLI разбит на множество пакетов @angular и CLI с разными версиями, что, в свою очередь, приводит к колоссальным проблема при апгрейде версии CLI/angular.
    Что и без того делается весьма не просто


С другой стороны Vue CLI 3 — самое крутое CLI на сегодня


  1. Кастомизация крайне удобна, любой пакет можно добавить в любой момент, благодаря системе плагинов
  2. Простота и гибкость, благодаря использованию webpack


Zone.js vs Vue Reactivity


Angular использует Zone.js для отслеживания изменений, который monkey-патчит для этого стандартные API, вроде setTimeout.


Это приводит к определенным проблемам:


  1. Сложности с нестандартными API, порой довольно сложно разрешимые
  2. Ужасные стектрейсы
  3. Вообще говоря ИМХО, это хак, причем далеко не самый элегантный

Vue не нужен Zone.js, отслеживание работатет благодаря превращению всех data/state пропертей в Observer.


В свое время увидев сорцы даже несколько расстроился, что нет никакой магии.


На верхнем уровне все тривиально: Vue проходится по всем пропертям через Object.defineProperty (именно по этой причине не поддерживается IE8 и ниже) и добавляет таким образом геттер и сеттер.


Даже особо нечего добавить...


Однако, у данного подхода есть подводные камни, но они предельно просто описаны и легки для понимания.
Причем понимания не столько Vue, сколько самого JS в его основе.


Во Vue нельзя динамически добавлять новые корневые реактивные свойства в уже существующий экземпляр. Тем не менее, можно добавить реактивное свойство во вложенные объекты, используя метод Vue.set(object, key, value):

var vm = new Vue({
  data: {
    a: 1
  }
})
// теперь vm.a — реактивное поле

vm.b = 2
// vm.b НЕ реактивно

Vue.set(vm.someObject, 'b', 2)

Надо также отметить, что с версии 2.6 Vue не будет иметь и этих проблем, т.к. произойдет переход на Proxy, и появится возможность также отслеживать добавление/удаление пропертей.


Rx и State Management


В Angular из коробки ядром фреймворка был RxJS, всё — Observable.
Несмотря на мою любовь к Rx, у меня и у многих возникали вопросы, о том, так ли он нужен внутри Angular'а?


Особенно на первых порах очень многие просто превращали Observable в промисы через .toPromise().


Да и вообще идея общей шины данных не самая простая для понимания, вдобавок к сложности самого Angular.


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


Существует NgRx, но полноценно юзабельным он стал не так уж давно — как результат, у нас даже есть старый проект с кастомной имплементаций Redux-подобного стора.


А теперь про Vue.


Мало того, что любой фанат RxJS сможет легко подключить его в любой момент, просто добавив новый пакет.


Уже даже есть Vue-Rx, позволяющий использовать RxJS Observabl'ы наравне с data.


Если говорить про State Management, то есть великолепный официальный Vuex.
В свое время с огромным удивлением обнаружил, что помимо него существует также огромное количество альтернатив.



Drop In


Собственно, тут и проявляется основное достоинство (хотя кому-то может показаться и недостатком) Vue — все можно подключить по необходимости.


Просто добавь:


  1. Воды
  2. RxJS
  3. Vuex
  4. TypeScript
  5. SCSS

Чего бы вам недоставало, оно всегда интегрируется просто и быстро.


Роутер


Причина одной из самых тяжелых психологических травм которую я получил от Angular — роутер.
Несмотря на то, что переписывался он уже трижды, он все еще ужасен (да, я повторяюсь).


Не буду описывать все его проблемы подробно, но так как тема наболевшая, кратко:


  1. Нет именованных роутов (!) — одно из самых странных решений, которое можно было принять это убрать именованные роуты, тем самым понизив удобство поддержки сложных приложений в разы
  2. Странная система ивентов, проверять которые нужно по типу,
  3. Превращение параметров роута в Observable — порой с ними крайне неудобно работать если они вам нужны только 1 раз при старте компонента
  4. Для навигации были придуманы команды, очень странное и мало полезное решение, более не используемое ни в одном роутере
  5. Lazy Loading через строковое название модулей, в приложении полностью на TypeScript… без комментариев
    … и т.д.

Если посмотреть сорцы, можно понять что многие из указанных проблем связаны со сложностью и функциональностью роутера.


То есть, даже не будь в нем странных решений вроде команд, количество фич все равно делает его сложным и тяжелым.


Во Vue роутер предельно простой и рабочий.


Говоря простой, надо упоминуть, что в свое время я не обнаружил привычного по Angular параметра abstract: true.


Из коробки нельзя сделать роут без шаблона, но это решается одной строчкой кода — созданием компонента вроде:


// AbstractRoute.vue
<template>
  <router-view/>
</template>

Плохо ли то, что подобной функциональности нет из коробки?


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


Кстати, вот классная штука:


    path: `url/sub-url/:id',
    component: MyComponent,
    props: true

Теперь у компонента MyComponent появится props id, который будет параметром из URL.
Это элегантное решение, т.к. id сразу будет реактивным и использовать его в компоненте очень удобно (опять же, просто работает).


Расширение и переиспользование


С одной стороны все компоненты в Angular — TypeScript классы.
Несмотря на это, использовать многие фишки TypeScript зачастую либо неудобно, либо невозможно вовсе.


Это относится в первую очередь к ООП — наследование, абстрактные классы, области видимости.
Основные проблемы возникают с Dependency Injection и AOT компайлером (упаси вас бог столкнуться с ними).


Во Vue же — конфигурация инстанса это объект – с ним просто работать и расширять, рефакторить.
Для переиспользования кода есть мощнейшие штуки — Mixin’ы и Plugin’ы (об этом ниже).


UI компоненты


В Enterprise сегменте компоненты обычно имеют готовый дизайн, мокапы и тд. Чаще всего они пишутся с нуля, сразу будучи заточенными под конкретную задачу/продукт/проект.
Но далеко не всегда у разработчиков есть возможность создавать все с нуля, особенно это касается pet проектов и прототипирования.


Тут на помощь приходят библиотеки готовые UI компонентов, и для Vue их существует уже великое множество: Element, Vuetify, Quasar, Vue-Material, Muse, iView, итд итд.



Особенно я бы отметил Element и Vuetify, впечатления строго положительные: красивые и стабильные компоненты для любых нужд, хорошие доки.


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


В случае Angular — Enterprise-level библиотек компонентов всего пара штук, это в первую очередь Angular Material (Google) и Clarity (VMWare).


К большому сожалению, темпы развития Clarity в последнее время снизились, что еще более расстраивает в плане перспектив Angular в данном вопросе.




Реальный опыт и проблемы


А теперь основные проблемы из реального опыта использования Vue на боевых проектах.


Слишком много свободы


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


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


Но, в реальности, это приводит к тому, что кодовая база становится довольно неконсистентной.


Утрированный пример: кастомную логику на странице можно сделать объявив некий компонент, причем он может быть как локальным


const Component = { created() { // logic ... }}

new Vue({
  components: [Component],

так и глобальным (доступным отовсюду).


Vue.component('Global', { created() { // logic ... }})

Можно сделать локальным Mixin который будет реализовывать данную функциональность


const mixin = { created() { // logic ... }}

new Vue({ mixins: [mixin],

причем он (примесь? она?..) опять же может быть глобальным.


Vue.mixin({ created() {// logic ... }})

В конце концов есть плагины, которые делают почти то же самое, что и глобальные миксины.


const MyPlugin = {
  install(Vue, options) {
    Vue.mixin({ created() { // logic ... }})
}

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


Код ревью необходим


Несмотря на то, что мы используем Vuex, я отметил для себя, что людям порой достаточно тяжело не использовать data() проперти вместо state.


Это вопрос скорее скорости — понятно что добавить что-то в data быстрее, но почти всегда получается так, что потом это необходимо будет выносить в state и тратить на это дополнительное время.


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


Могу предположить что работать с таким кодом через несколько месяцев станет совсем неприятно.


Юнит тесты


Также, после Angular, было не очень удобно и очевидно мокировать некоторые вещи в Jest.
Конкретный пример — local storage. Кто-то решил это нагуглив данный issue на гитхабе.


Object.defineProperty(window, 'localStorage', {
  value: localStorageMock,
})

Мне решение красивым не показалось, но как потом выяснилось, есть и более элегантное


global.localStorage = localStorageMock;

Да, это не проблема Vue, но проблема экосистемы в сравнении с Angular.


На мой взгляд, именно подобные реальные примеры должны быть описаны в документации.


Cookbook


Вообще, ребята из Vue знают об этой проблеме и решают ее посредством написания Cookbook с рецептами.
Фактически это набор готовых решений на популярные задачи.
Вот например: юнит-тесты,
валидация и работа с HTTP.


Однако, рецепты пока довольно базовые и их сильно не хватает для серьезных задач.
Тесты описаны и для общего понимания этого достаточно, но упомянутое выше мокирование придется искать самому.


На валидации я остановлюсь позже, но вот работа с HTTP точно описана недостаточно глубоко.


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


Но так как пресловутого DI у нас нет, а самому создавать инстансы сервисов не очень удобно, хотелось бы иметь подобный паттерн в Cookbook.


Данную проблему мы по большей части решили выработкой локальных code conventions и best practices. Ссылки в конце статьи


TypeScript


Я уже множество раз говорил и писал, о том как крут и полезен TypeScript, но факт в том, что его надо уметь готовить.


В Angular все завязано на экспериментальные фичи (декораторы), внутренние классы и сотни (тысячи?) излишних абстракций.



Во Vue возможное использование TypeScript гораздо более логично — оно лишь позволяет расширить возможности разработчика, без необходимости завязываться на те или иные возможности языка.


Проблемы с TypeScript в Vue


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


Во-первых они так и не приняли мой Pull Request из-за своих же поломанных тестов =(((


Шутка, конечно же, это только моя личная боль


Два подхода


Основной проблемой TypeScript во Vue я бы назвал то, что есть два разных официальных подхода к его использованию.


Это Vue.extend (тайпинги идущие в комплекте с Vue из коробки и поддерживаемые наравне с основной библиотекой)


import Vue from 'vue'

const Component = Vue.extend({
  ...
})

и очень схожий с Angular декоратор vue-class-component


import Vue from 'vue'
import Component from 'vue-class-component'

@Component({
  template: '<button @click="onClick">Click!</button>'
})
export default class MyComponent extends Vue {
  message: string = 'Hello!'

  onClick (): void {
    window.alert(this.message)
  }
}

Лично мне не нравится class-component, и по ряду причин мы используем Vue.extend:


  1. У class-component есть свои хитрости / недостатки
  2. Хочется как можно меньше уходить от дефолтных ES6 Vue компонентов
    • И использовать код прямо из документации, без необходимости править для TS
  3. Необходимо, чтобы команда понимала как работает Vue без TypeScript
    • Особенно, учитывая что большинство имеет Angular бэкграунд

Другие проблемы


Вот еще некоторые проблемы с TypeScript, разной степени печальности:


  1. TSlint из коробки не работает с Vue — до сих пор нельзя запустить для .vue файлов. Вообще есть решения через fork-ts-checker, но все они некрасивые
  2. ESlint для TypeScript еще мягко говоря не супер. И plugin и parser еще в стадии разработки.
    Многие core и vue правила ломаются, но основная проблема в том, что возникают крайне непонятные ошибки.
    Однако, несмотря на это, мы используем именно его, отключив сломанные правила и подкрутив нужные.
    Ссылка на наш конфиг ESlint.
  3. Vuex store не типизирован снаружи, соответственно вызовы this.$store из компонента возможны фактически с любым payload

Но и Vue.extend(), в свою очередь, имеет некоторые минусы:


  1. Нельзя использовать как класс (ваш капитан), соответственно никаких приватных, статических методов и тд.
  2. Боль c мапперами из Vuex …mapGetters(), …mapState() и тд. При использовании этих мапперов теряется типизация и появляются странные ошибки. Ждем пока зальют решение
  3. Типизация data() пропертей неудобна, т.к. это функция — каждый раз приходится создавать интерфейс описывающий ее возвращаемое значение
  4. Честная типизация props вообще практически невозможна, т.к. необходимо объявлять нативный JS тип, а ожидается обычно TypeScript интерфейс, но есть некрасивое решение с кастингом

// Тип реального значения приходящего в myObjectProps
interface MyType = {...}

// Пример типизации data
interface MyComponentData = {
  someBooleanProp: boolean;
}

export default Vue.extend({
  data(): MyComponentData { // Указание возвращаемого функцией data значения
    return {
      someBooleanProp: false
    };
  },
  props: {
    myObjectProps: Object as MyType // кастинг к TS интерфейсу
  },

Формы с Vuex


Вообще формы это проблема не только Vuex, а почти любого State Management паттерна.
Все-таки он предполагает односторонний поток данных, а формы подразумевают двусторонний байдинг.


Vuex предлагает два варианта решения.


Через привязку value к значению state, а для обновления — событие input с отправкой коммита:


<input :value="message" @input="updateMessage">

// ...
computed: {
  ...mapState({
    message: state => state.obj.message
  })
},
methods: {
  updateMessage (e) {
    this.$store.commit('updateMessage', e.target.value)
  }
}

Или все же использовать двусторонний байдинг и v-model а получение и коммит осуществлять через геттер и сеттер:


<input v-model="message">

// ...
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}

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


Проблема чуть менее актуальна если использовать мапперы, а именно mapGetters() и mapMutations(),
но, как я писал выше, они в данный момент с TypeScript плохо работают и пришлось искать другое решение.


Мы написали примитивнейший маппер, который добавляет геттер (геттер из state) и сеттер (коммит мутации):


static mapTwoWay<T>(getter: string, mutation: string) {
  return {
    get(this: Vue): T {
      return this.$store.getters[getter];
    },
    set(this: Vue, value: T) {
      this.$store.commit(mutation, value);
    }
  };
}

Он позволяет сократить количество кода и описывать поля подобным образом:


stringTags: Util.mapTwoWay<IDatasetExtra[]>(STRING_TAGS, UPDATE_STRING_TAGS)

И, соответственно, использовать v-model:


v-model="stringTags"

Валидация форм


Что несколько удивило после Angular — из коробки во Vue нет валидации форм. Хотя, казалось бы, фича весьма востребованная.


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


vee-validate


Первое — это весьма схожий механизм с template-driven формами в Angular — vee-validate.


Фактически вы описываете всю логику валидации в HTML.


<input v-validate="'required|email'">

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


Плюс это не очень красиво работает с Vuex.


vuelidate


Второе решение — Vuelidate. Невероятно элегантный способ валидации почти любых компонентов — валидируется сама модель, а не тот или иной input.


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


<input v-model="name" @input="$v.name.$touch()">

import { required, email } from 'vuelidate/lib/validators'

export default {  
  data () {
    return {
      name: ''
    }
  },
  validations: {
    name: {
      required,
      email
    }
  }
}

Очень рекомендую при необходимости валидации форм сразу рассматривать Vuelidate — он отлично работает (в том числе с Vuex), легко подключается и кастомизируется.


Основная фишка/проблема Vue


Собственно, в этом и состоит основная проблема (?) Vue — это только библиотека, а не навороченный фреймворк all-in-one.


Из коробки нет:


  • HTTP
  • Валидации
  • i18n
  • … и тд?

Да, есть официально поддерживаемые:


  • Router
  • State
    Но, все же это отдельные пакеты, а не ядро.

Однако, при всем этом, во Vue из коробки есть такая крутая встроенная штуки как Animation ???


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


Это, пожалуй, гораздо более удобный и мощный тулсет, нежели в том же Angular.


Классный пример из документации:



Nightwatch и e2e


Небольшая проблема, снова не связанная напрямую с Vue, но с которой мы столкнулись на реальном проекте.


Из коробки при генерации проекта для e2e тестирования есть выбор между Nightwatch и Cypress.


Несмотря на то, что Cypress лично мне видится как самый классный инструмент для e2e тестирования на сегодня, поддержка браузеров отличных от Chrome до сих пор отсутствует.


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


Однажды наши тесты начали падать на Linux CI по совершенно необъяснимой причине (на Windows все было ок), при этом ошибки не были информативны.
Позже удалось выяснить, что проблема связана с хешами (#) в URL'ах.
А именно такие URL'ы и будут по умолчанию при использовании vue-router.


К сожалению, это вроде бы проблема селениума или ChromeDriver, а не Nightwatch (еще один повод смотреть в сторону Cypress и TestCafe), но на текущий момент решением будет "обнулять" url перед открытием хешированных:


.url('data:,')
.url(client.globals.devServerURL + `/#/my-hashed-url`)

Что мы отметили


Скорость разработки


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


Все решения во фреймворке направлены на минимализм, как с точки зрения функционала, так и с точки зрения Developer Experience. Могу сказать, что наша команда реально стала больше успевать.


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


Чего нет


Чего действительно пока не хватает Vue — достойной альтернативы React Native.
Ни один из подобных фреймворков для мобильной разработки нельзя с ним сравнить.


Да, для Vue есть NativeScript Vue, но он, на сегодня, значительно менее мощный.
Также есть Weex, но использовать его в реальных проектах я бы пока не стал, так как он еще развивается и не слишком стабилен.


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


Для себя мы также обратили внимание на шикарную скорость работы фрейморка. Особенно это касается первоначального открытия страницы.




Более подробный тест производительности можете посмотреть здесь: http://www.stefankrause.net/js-frameworks-benchmark7/table.html
(помимо "большой тройки" там есть огромное количество других фреймворков и не только).


И напоследок пара ссылок на мнения более авторитетных товарищей: GitLab,
CodeShip, Alibaba, Xiaomi.


Вывод


Из всего описанного выше мы сделали некоторые выводы.


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


Мы используем его уже в нескольких проектах, в том числе вот вот выходящих в production.
Более того, четко очертив для себя проблемы и их решения, мы научились работать с TS так же быстро и удобно во Vue, как это делается на JavaScript.


Но все же, хотелось бы, чтобы в более свежих версиях, поддержка TypeScript улучшилась.


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


Так что, "если вы еще кипятите", очень рекомендую хотя бы попробовать Tide Vue и самим почувствовать разницу.


Наши code conventions


Чтобы ваш опыт был еще более приятным, вот обещанные выше соглашения по коду от нашей команды, может быть вам пригодятся.
Безусловно они очень субъективны, но иначе быть не может.


Стиль кода и структура приложения


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


Это наш Vue seed (TS, кастомные настройки Jest, ESlint и т.д.), в данный момент, до выхода в релиз Vue CLI 3,
он сгенерирован на предыдущей версии и представляет из себя не темплейт а репозиторий.
Готовится версия для разворачивания с помощью Vue CLI 3 через шаблон.


И это все??

Да. Спасибо за внимание.

PS: После прочтения может показаться, что у Vue больше минусов чем плюсов — просто не хочется писать очередную хвалебную статью, ведь их и так полон гугл


PPS: Кстати английский вариант предыдущей статьи был настолько успешен, что у меня даже состоялось прямое общение (видео) с основными виновниками — но работу не предложили =(

Комментарии (33)


  1. JustDont
    17.05.2018 12:17

    Главной (хронической?) болью от ангуляра для меня остались даже не их местами дико монструозные решения, а отношение к разработке.

    Пользователи ангуляра используют фичу Х не по назначению и стреляют себе в ногу? Мы просто уберем фичу Х. Чтоб не говорили, что ангуляр тормозит. Вы использовали её по назначению? Нас не волнует.

    Вы хотите наследование в ангуляре? Вы возмущены тем, что всю нашу документацию мы старательно прикидываемся ООП-комплементарными, а на самом деле нет? Мы за вас очень страдаем, но наследование делать не будем. Потому что это очень сложно™.


    1. SaturnTeam
      18.05.2018 08:04
      +1

      Если я правильно понял, то наследование компонентов станет доступным после выхода Ivy render. И о какой фиче идет речь?


      1. MooooM Автор
        18.05.2018 10:30

        Хорошим примером полезных добавленных, но позже безвозвратно убранных фич в Angular будет пресловутый роутер, а именно: именованные роуты (да они были) и, например, route reuse.


        Про второе вообще можно написать отдельный пост — но суть, что раньше это был просто один параматр вроде reuse: false, а теперь нужно имплементировать немаленький класс RouteReuseStrategy


      1. JustDont
        18.05.2018 12:15

        Я много смотрел на рассказы об Ivy, но не заметил там ничего на тему наследования. Если говорить предметно, то наследование в ангуляре можно выразить и сейчас (typescript-то наследовать и вовсе никто не помешает, а с декораторами есть определенные решения), просто это, мягко говоря, совсем кривые способы.

        И о какой фиче идет речь?

        К сожалению уже не вспомню, больше чем полгода прошло. Но про роутер хорошо написано. Крайне грустно видеть, что раньше роутер был гораздо более адекватен в применении, чем роутер сейчас.


  1. k12th
    17.05.2018 12:45

    Vue.mixin({ created() {// logic… }})

    Я бы сказал это нужно только когда вы делаете фреймворк и хотите экспортировать этот миксин наружу, т.к. он полезен сам по себе. Ну или когда этот миксин действительно используется в большом количестве компонентов.
    Красота миксинов в том, что a) это просто объект и b) его легко использовать в любом количестве компонентов, не загрязняя общий инстанс Vue.


    В конце концов есть плагины, которые делают почти то же самое, что и глобальные миксины.

    А вот это совсем не правда. Миксины просто добавляют свойства и методы в данный компонент, в то время как плагины позволяют манипулировать Vue каким угодно образом. Vuex работает как плагин, а не как миксин, vue-router тоже.


    1. MooooM Автор
      17.05.2018 12:53

      Эх, я же специально написал что пример утрированный.
      Поверьте, я хорошо понимаю разницу между миксином и плагином, к тому же написал, что и то и другое — очень полезный функционал.

      Поинт в том, что есть степени свободы в сравнении с Angular. Можно также привести пример с computed vs watched property. Опять же, они преследуют разные цели и нужны для разных задач, но новичкам (особенно), не всегда очевидно что использовать и где.


  1. lega
    17.05.2018 14:42

    Производительность
    По вашей ссылке vue прогигрывает ангуляру: 1.38 против 1.28, а в статье наоборот, как так?
    Vue не будет иметь и этих проблем, т.к. произойдет переход на Proxy, и появится возможность также отслеживать добавление/удаление пропертей.
    Переход будет когда все (необходимые) браузеры будут это поддерживать, а не когда будет релиз vue.


    1. MooooM Автор
      17.05.2018 14:48

      Касательно производительности взята часть таблицы — если брать все результаты, разницы почти не будет, поэтому я и написал, что основное заметное место большей скорости работы Vue — начальная загрузка страницы.
      Но даже так, коэффициэнт который я вижу по ссылке — 1.14, и уж никак не ниже у Angular против Vue. Вы точно сраниваете обычные версии а не с vuex, no-zone и тд?


    1. JustDont
      17.05.2018 14:56

      1.28 у ангуляра без использования Zone.js. Что лишает его некоторых фич, ну и всё-таки это «возьмите наш крутой фреймворк и сами доработайте молотком».
      У просто ангуляра всё те же 1.38.


  1. khraks_mamtsov
    17.05.2018 14:48

    Для DI можно использовать InversifyJS — совместим со vue-class-component через LazyInjection декоратор — можно инжектировать не через конструктор.

    Не увидел у вас vue-property-decorator и vuex-class в seed. Принципиально не используете?


    1. MooooM Автор
      17.05.2018 14:53

      Про InversifyJS в курсе, но именно и не хочется тащить все это на фронт-энд.
      Он очень пригодится для Node, но в обычным Vue приложениях считаю слишком большим оверхедом.

      Вообще, то же самое касается и vue-property-decorator и vuex-class — как раз то место в статье, где описаны причины использования Vue.extend.
      Все эти вещи добавляют дополнительную сложность и TS специфику там, где изначально она не предусмотрена — больше проблем и сложнее поддержка.
      Мы стремимся использовать сторонние вещи только по необходимости.

      ЗЫ: vuex-class использовал на pet проекте, проблемы были, а большой пользы не ощутил


    1. Focushift
      17.05.2018 19:59

      А как же vue-inject?


  1. IvanNochnoy
    17.05.2018 14:52

    Главное отличие Vue от Angular в том, что Angular предназначен только для SPA-приложений. В остальном Vue очень похож на Angular особено в нотации, основанной на классах. Я знаю, что внутри сделано иначе, но для меня, как для разработчика, это не важно, раз я все равно не вижу этого. Если вы будете добавлять, то чего нет из коробки, то, в конечном итоге, получится… Angular. Это мое мнение, хотите — верьте, хотите — нет.


    1. k12th
      17.05.2018 15:04

      Angular предназначен только для SPA-приложений

      А Vue для чего предназначен? оО


      1. IvanNochnoy
        17.05.2018 15:14
        +1

        Vue возможно использовать как замену jQuery/Vanilla JavaScript на классических многостраничных сайтах, то есть без клиентского роутинга, и без API. С Angular это не прокатит так как там есть только один единственный корень приложения.


        1. k12th
          17.05.2018 15:19

          В Angular 1.x точно так же было можно посадить приложение на любой узел в дереве, не знал, что из 2.x это убрали.


          1. IvanNochnoy
            17.05.2018 15:21

            Я тоже не знал, а когда узнал, было уже поздно.


        1. JustDont
          17.05.2018 19:00

          Это будет неудобно, но почему «не прокатит»-то? При желании можно и несколько аппликух впихнуть на одну страницу (по крайней мере, пока у них ангулярские зависимости полностью совпадают по версиям), и в многостраничный контекст их вписать, в произвольной N-to-N конфигурации.

          В js можно примерно всё. Вопрос только в том, скольких усилий это будет стоить в реализации и в поддержке.


          1. IvanNochnoy
            17.05.2018 19:18

            Потому что в официальной доке Angular по поводу non-SPA приложений нет ни слова. Есть где-то хак на каком-то форуме с ручным бутстрапом, но сами Google его не используют, как говорится на свой страх и риск. Обещают в шестой версии запилить Angular Elements, но это уже не фреймворк будет.


            1. JustDont
              17.05.2018 19:19

              Конечно. Именно поэтому я и написал, что «будет неудобно». И поддерживать это будет неудобно. И так далее.

              Но сделать-то можно, и даже без моря усилий.


              1. IvanNochnoy
                17.05.2018 19:31

                Удачи!


    1. kemsky
      19.05.2018 04:10

      Вообще они вроде как сделали возможность использовать отдельные компоненты на странице не превращая все в SPA, см. Angular Elements.


  1. saw_tooth
    17.05.2018 16:57

    Из коробки нет:
    HTTP
    Валидации
    i18n
    … и тд?

    А мне кажется это больше преимущество, нежели недостаток.
    Как в противовес можно сопоставить python flask и django.


  1. zeonz
    18.05.2018 10:23

    Вы не упомянули Single File Components — на мой взгляд это одна из главных фич, которая заставляет влюбиться во Vue. Любопытно, а почему вы используете Vue.extend а не SFC? По поводу тестирования у Vue есть схожая с React библиотека тестирования (написание тестов очень похоже)


    1. MooooM Автор
      18.05.2018 10:24

      Именно SFC мы и используем (смотри код стайл раздел), Vue.extend необходим для поддержки TypeScript, примерно как здесь.


    1. IvanNochnoy
      18.05.2018 11:02

      А чего влюбляться-то? Свалить всё в одну кучу можно и в Реакте и Ангуляре.


    1. serf
      18.05.2018 16:13
      -1

      А чем удобно все сваливать в один файл? Я бы делал шаблон в этом vue файле, а скрипт и стили подключал обычным образом (link / script теги) — vue поддерживает такой подход. Тогда получились бы трех файловые компоненты, что как по мне удобнее по многим причинам, а на выходе после сборки пускай это будет 1 файл.


      1. MooooM Автор
        18.05.2018 16:17

        На самом деле никто вам не запрещает, это отлично поддерживается Vue.

        Нам нравится в первую очередь с точки зрения файловой структуры — очень удобно работать с едиными файлами.
        С точки зрения IDE работа с .vue файлами очень удобна — подсветка синтаксиса работает, сворачивание, итд.

        У нас общие стили вынесены в отдельные обще-проектные стилевые файлы, а компоненты имеют только специфичные им стили. Таким образом стили в .vue довольно небольшие, а то и отсутствуют вовсе.
        Примерно так же и для шаблона. Скрипт тег также обычно довольно короткий, так как основная логика находится в store.


  1. serf
    18.05.2018 16:16

    PPS: Кстати английский вариант предыдущей статьи был настолько успешен, что у меня даже состоялось прямое общение (видео) с основными виновниками — но работу не предложили =(

    Статей от товарищей с реальным опытом немного, в основном все по верхам, успешность заслуженная.


  1. kemsky
    19.05.2018 04:30

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


    angular-cli я не пользуюсь, как и react-scripts и даже vue-cli, вебпак или роллап более-менее поддаются настройке и не лишают меня свободы выбора и не добавляют лишних проблем.


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


  1. Brotandos
    19.05.2018 08:42

    Насчет Tslint: в vscode поддерживается в файлах с расширением .vue
    Видимо вы используете WebStorm


    1. MooooM Автор
      19.05.2018 12:26

      В VScode оно может и работает, но не через сам пакет линтера — т.к. отдельно он не умеет этого. Соответственно, нельзя запустить на CI — а значит толку от такого линтера немного.


    1. serf
      19.05.2018 12:30

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