[Перевод] 4 рекомендации по разработке крупномасштабных проектов на Vue

Как известно, Vue.js — это фреймворк, основанный на JavaScript, популярность которого в последние годы стремительно растёт.

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

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

e9a7lwvli0jbskri_8ld0e6sfxm.jpeg

В этом материале я хочу представить вашему вниманию 4 развёрнутых рекомендации по разработке крупномасштабных Vue-проектов.

1. Используйте слоты Vue для того чтобы сделать код понятнее


При настройке взаимоотношений компонентов чаще всего используют модель «родитель-ребёнок». Но в некоторых ситуациях такая модель может оказаться далеко не самой удачной. Представьте себе, что у вас имеется один родительский компонент, в котором размещено большое количество дочерних компонентов. Это означает, что вам, для налаживания взаимодействия компонентов, придётся использовать большое количество входных параметров (props) и генерировать множество событий. В таких условиях в коде очень быстро заведётся беспорядок. Именно с такими ситуациями сталкиваются разработчики крупномасштабных проектов. Но во Vue есть механизмы, предназначенные именно для решения подобных проблем.

Речь идёт о слотах. Они применяются для организации альтернативного способа представления взаимоотношений типа «родитель-ребёнок». Слоты, а именно — элементы , дают разработчику возможность по-новому организовывать код. Вот простой пример использования слота:

   


Когда такой компонент будет рендериться, в нём тег будет заменён содержимым тега :


  

Hi!

  


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

2. Создавайте независимые компоненты и многократно используйте их


При разработке компонентов следуйте принципу FIRST, делая компоненты узконаправленными (Focused), независимыми (Independent), пригодными для многократного использования (Reusable), маленькими (Small) и тестируемыми (Testable).

На самом деле, секрет эффективной разработки «больших» систем заключается в том, чтобы не стремиться, в первую очередь, создавать эти системы. Вместо этого нужно собирать эти системы из меньших фрагментов, решающих узкоспециализированные задачи. Это упрощает оценку того, как мелкие части систем согласуются с их «большими» целями.
Эдди Османи

Для создания компонентов и для управления ими можно пользоваться специализированными системами наподобие Bit. Вот материал об этом.

3. Поддерживайте хранилище Vuex в хорошо организованном состоянии


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

Прежде чем говорить об этих принципах, мне хотелось бы рассказать о 4 основных компонентах хранилищ Vuex, о которых нужно знать тем, кто хочет эффективно пользоваться такими хранилищами. Если вы знакомы с этими компонентами, это значит, что вы сможете легко структурировать ваше хранилище Vuex и улучшить организацию проекта. Вот их краткое описание:

  • Состояния (states): используются для хранения данных приложения.
  • Геттеры (getters): применяются для организации доступа к объектам состояния за пределами хранилища.
  • Мутации (mutations): нужны для модификации объектов состояния.
  • Действия (actions): используются для применения мутаций.


Исходя из предположения о том, что вы знакомы с этими компонентами, давайте поговорим о вышеупомянутых принципах:

  1. Состоянием уровня приложения нужно управлять централизованно, размещая его в хранилище.
  2. Изменения в состояние всегда должны вноситься с использованием мутаций.
  3. Асинхронная логика должна быть инкапсулирована, она должна воздействовать на состояние только посредством действий.


Если вы сможете придерживаться этих 3 принципов, это значит, что вы сможете хорошо структурировать проект. Если же в ходе роста проекта вы решите, что код соответствующих компонентов Vuex нужно разместить в различных файлах — вы вполне сможете это сделать. Ниже показан пример структуры проекта, использующего Vuex:

├── index.html
├── main.js
├── api
├── components
└── store
    ├── index.js          
    ├── actions.js
    ├── mutations.js
    └── modules


▍Модульная организация хранилища Vuex


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

Вот пример модульного подхода к структурированию хранилища:

store/
   ├── index.js 
   └── modules/
       ├── module1.store.js
       ├── module2.store.js
       ├── module3.store.js
       ├── module4.store.js
       └── module5.store.js


▍Использование вспомогательных методов


Выше я говорил о 4 компонентах, используемых в хранилищах Vuex. Рассмотрим ситуацию, когда нужно обращаться к состояниям и работать с геттерами, когда необходимо вызывать в компонентах действия и мутации. В подобных случаях не нужно создавать множество методов или вычисляемых свойств. Здесь можно просто воспользоваться вспомогательным методами (mapState, mapGetters, mapMutations и mapActions), применение которых позволит избежать неоправданного увеличения объёма кода. Поговорим об использовании этих вспомогательных методов.

▍mapState


Если в компоненте нужно обращаться к нескольким свойствам хранилища или к нескольким геттерам, это значит, что мы можем воспользоваться вспомогательным методом mapState для генерирования функции-геттера. Это избавит нас от необходимости написания сравнительно больших объёмов кода.

import { mapState } from 'vuex'
export default {
  computed: mapState({
    count: state => state.count,
    countAlias: 'count',
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}


▍mapGetters


Вспомогательный метод mapGetters используется для настройки сопоставления геттеров хранилища с локальными вычисляемыми свойствами.

import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters([
      'count1',
      'getter1',
    ])
  }
}


▍mapMutations


Вспомогательный метод mapMutations используется в компонентах для применения мутаций. Он задаёт соответствие между методами компонента и вызовами store.commit. Кроме того, этот метод можно использовать для передачи в хранилище каких-то данных.

import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations({
      cal: 'calculate' // отображает `this.cal()` на `this.$store.commit('calculate')`
    })
  }
}


▍mapActions


Вспомогательный метод mapActions применяется в компонентах для диспетчеризации действий. Он задаёт соответствие между методами компонента и вызовами store.dispatch.

import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions({
      cal: 'calculate' // отображает `this.cal()` на `this.$store.dispatch('calculate')`
    })
  }
}


4. Не забудьте о модульных тестах


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

Если говорить о модульных тестах, применяемых в проектах, основанных на Vue, то можно сказать, что такие тесты практически идентичны тем, что применяются в проектах, основанных на других фреймворках и библиотеках. А именно, с Vue хорошо сочетаются Jest, Karma или Mocha. Но, независимо от того, какой именно фреймворк выбран для создания тестов, есть несколько общих рекомендаций, которые следует учитывать, разрабатывая модульные тесты:

  • Если тест завершился неудачно — он должен выводить чёткие сообщения об ошибках.
  • При создании тестов рекомендуется использовать хорошие библиотеки для формирования утверждений. (Например, механизмы для формирования утверждений встроены в Jest, а с Mocha используется библиотека Chai).
  • Модульные тесты должны покрывать все компоненты Vue.


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

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

Итоги


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

Как вы думаете, подходит ли Vue для разработки крупномасштабных проектов?

oug5kh6sjydt9llengsiebnp40w.png

© Habrahabr.ru