Как оригинальный Java-программист и разработчик приложений для iOS, мне всегда было немного неудобно в мире Javascript. Мне всегда казалось, что я стою на большой «Башне Дженга», и чем больше и больше росло приложение, тем менее очевидными были последствия удаления или изменения определенных фрагментов кода.

Отсутствие типов и еще не полная поддержка всех объектно-ориентированных принципов затрудняло написание правильного кода. Не поймите меня неправильно, с обновлением ES5, ES6 стало намного лучше, но все равно чего-то не хватало ...

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

Вот почему мы решили начать наш следующий проект с совершенно нового стека и попытаться описать наш опыт в блоге. Он написан для людей, которые уже имеют опыт работы с Vue JS и знают основные концепции компонентов, vuex, vue-router и вызовов веб-сервисов.

В новый стек включены следующие технологии:

Интерфейс (часть 1)

  • Vue JS с Typescript
  • vue-cli 3.0 alpha (теперь поддерживает Typescript)
  • vuex
  • Bulma CSS Framework
  • Cypress (для интеграционных тестов)
  • Mocha / chai (для юнит-тестов)

Серверная часть (часть 2)

  • Lumen 5.6 (микро-фреймворк на основе Laravel)
  • Mailgun (для рассылки)
  • phpunit для тестирования

Непрерывная интеграция (часть 3)

  • Gitlab CI / CD
  • Автоматизированное тестирование
  • Автоматическое развертывание
  • Инструмент мониторинга для всех проектов

Святой, это много всего. Поэтому я решил разделить это на 3 части (фронтенд, бэкэнд и непрерывная интеграция).

Начнем с интерфейса

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

Настройка проекта Vue JS с помощью Typescript
К счастью, хорошие ребята из Vue JS Team недавно обновили альфа-версию vue-cli со встроенной поддержкой Typescipt. Это упрощает создание Vue JS SPA с помощью сценария vue-cli на основе командной строки.

Я не хочу объяснять, как создать свой проект на основе vue-cli, вы можете найти всю информацию по данной ссылке: https://github.com/vuejs/vue-cli

Структура папок проекта

Мы использовали сгенерированную структуру папок из vue-cli и добавили несколько папок.

Интересная папка - src. Вот краткое описание вложенных папок:

src / assets
Включает все файлы изображений / sass.

src / components
Здесь хранятся все компоненты Vue JS. Мы группируем их во вложенные папки на основе модулей, чтобы поддерживать порядок.

src / helpers
Здесь хранятся вспомогательные классы.

src / models
В своих мобильных приложениях я всегда отображал ответы API (JSON) в объектную структуру. Для управления всеми этими моделями я создал эту папку моделей.

src / routing
Все маршруты во внешнем интерфейсе управляются пакетом vue-router. Здесь хранится основной файл конфигурации.

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

src / vuex
Для локального хранения данных мы используем vuex в сочетании с плагином vuex-persistedstate. Мы разделили файл магазина на подмодули. Как мы это сделали, будет объяснено в следующем разделе.

src / webservices
Все классы веб-сервисов реализованы здесь как классы Singleton и могут использоваться во всех компонентах.

От API к компоненту Vue JS

Чтобы вы лучше понимали, как все работает вместе, я хочу показать вам, как вызов API из класса Webservice привязан к модели и как данные позже отображаются в компоненте на основе Vue JS.

Ответ JSON и классы модели
В этом примере у нас есть ответ JSON с темой, которая содержит несколько параметров. С Typescript у нас есть то преимущество, что нам больше не нужно работать с нетипизированными словарями Javascript. Наконец-то мы можем работать напрямую с типизированным деревом объектов, где Visual Studio Code автоматически показывает с Intellisense возможные переменные.

Класс Webservice
В более ранних проектах мы выполняли наши запросы axios непосредственно в компонентах Vue. Это позволяет дублировать код. Вот почему мы решили создать теперь отдельные классы веб-сервисов для каждого модуля. В следующем коде вы можете увидеть файл реализации TopicWebservice, который отвечает за конечную точку на api (api / v1 / topic).

Компонент Vue JS
Этот компонент Vue JS отображает выбранные темы и вопросы.

Приятно то, что в этот компонент Vue JS мы можем просто включить класс TopicWebservice и вызвать метод getAllTopics. Возвращенное обещание включает сопоставленные темы со всеми соответствующими параметрами.

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

Использовать геттеры из vuex в Typescript также довольно просто. Мы использовали декораторы vue-property-decorator и vuex-class, чтобы напрямую связать переменную-получатель themes с переменная класса в Typescript.

В этом компоненте Vue JS мы передаем все темы субкомпоненту (блок вопросов), который отвечает за отображение тем и параметров.

Vuex и использование локального хранилища

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

Мы начали использовать следующую структуру для наших модулей vuex.

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

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

Вот наша текущая версия файла магазина в теме модуля. Он включает состояние, мутации, действия и геттеры. Они сгруппированы в модуль, который затем включается в основной файл магазина. Очень важно namespaced: true, иначе он не будет работать с разделенными пространствами имен.

Конфигурация маршрутизации

В качестве внутреннего маршрутизатора представлений мы используем vue-router, который также готов к работе с Typescript. Здесь ничего особенного. Просто соединяет дорожки с компонентами.

Интеграционные тесты с Cypress

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

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

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

Непрерывная интеграция
Небольшой тизер к Части 3 ..! Наконец-то нам удалось настроить Gitlab CI / CD для запуска наших тестов cypress на сервере и автоматического развертывания его на нашем сервере разработки, когда тесты были успешно выполнены в основной ветке. Теперь у нас также есть небольшой монитор, показывающий статус наших текущих проектов git.

Это на данный момент

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

Части 2 и 3 появятся в ближайшее время и будут связаны здесь.