В 2021 году на рынке фронтенд-технологий лидируют React, Angular и, с некоторым отставанием, Vue. В нашей компании для унификации подбора разработчиков сделан упор на React, но ряд крупных систем разрабатываются с помощью современных версий Angular. В связи с конкуренцией этих технологий возникло желание изучить каждую из них и составить собственное мнение о применимости этих инструментов.
Приложение по аналогии с «Туром героев» будет состоять из главной dashboard-страницы, страницы с управлением навыками и сотрудниками, и с детализированными страницами по каждому навыку и сотруднику. Текущий дизайн приложения далёк от совершенства, основная цель — изучить логику работы с Angular и React при создании приложения.
На главной странице в MVP приложения выводим самых критичных сотрудников, чьи навыки надо забирать всей остальной команде
На странице с управлением навыками и сотрудниками мы увидим две колонки, в каждую из которых можно добавить новый навык или указать имя нового сотрудника. Навыком может быть как знание какой-то критически важной технологии, так и глубокое понимание работы того или иного микросервиса или фронт-проекта, эксплуатируемого командой. Для каждого навыка отображается, сколько сотрудников его знают, а для каждого сотрудника — количество освоенных им навыков.
Страницы с детализацией навыков и сотрудников похожи: на них можно отредактировать название навыка или имя сотрудника, а также нажатием на элемент из списка пометить, что сотрудник изучил навык (тогда красный восклицательный знак сменится на зелёную галочку).
Попробовать проект вживую можно вот тут: https://bus-factor.web.app, ссылка на кодовую базу — https://github.com/domclick/bus_factor
Всего две сущности — «Сотрудники» и их «Навыки», и таблица для прикрепления навыка к сотруднику. Для взаимодействия с этими сущностями были написаны мы написали Angular-сервисы, которые реализуют необходимый CRUD для общения с Firebase-бекендом:
Код
Описанный выше дизайн было решено реализовать на следующем наборе компонентов:
dashboard
Главная страница довольно простая, уместилась в один компонент. Чтобы одновременно загрузить данные и по сотрудникам, и по их связанным навыкам, используем forkJoin из rxjs. Полученные данные подготавливаем с помощью набора циклов и сортировки (которые наверняка можно было написать оптимальней), и получаем следующий файл:
Код
bus-factor-list
Страница для управления навыками и сотрудниками использует компоненты skill-item и employee-item. Для получения событий из дочерних компонентов и реакции на них используем директиву Output, обработав полученные данные в handleDeleteSkill и handleDeleteEmployee.
Код
В целом код для сущностей «Сотрудник» и «Навык» в MVP очень похож, но я не стал убирать дублирование кода, потому что в дальнейшем каждый компонент будет кастомизироваться. Typescript-логика для bus-factor-list выглядит так:
Код
skill-item
Для того, чтобы просклонять в зависимости от численности слово «сотрудник», был использован pipe pluralize:
Код
В компонент skill-item он подключается следующим образом:
<div class="skill-container" (click)="onSkillClick()">
<div class="skill-info">
<div class="skill-name">{{ skill.name }}</div>
<div class="skill-skills">
{{ skillCount }} {{ skillCount | pluralize: ['сотрудник', 'сотрудника', 'сотрудников'] }}
</div>
</div>
<button class="delete" title="delete skill"
(click)="deleteSkill(skill)">
Удалить
</button>
</div>
Внутри Typescript-логики можно увидеть использование события Output:
Код
skill-detail и employee-detail
На страницах с управлением навыками каждого сотрудника (employee-detail), а также на странице с редактированием навыка и списком сотрудников, обладающим этим навыком (skill-detail) можно увидеть использование директивы ng-template в else-блоке отображения наличия/отсутствия навыка:
<div class="card-title">Управление навыком</div>
<div class="skill-info">
<div class="skill-id"></div>
<input [(ngModel)]="skill.name" placeholder="Название навыка"/>
<div class="skill-controls">
<button (click)="goBack()">Назад</button>
<button (click)="save()">Сохранить</button>
</div>
</div>
<div class="skill-box">
<div class="skills-title">Сотрудники с этим навыком</div>
<div class="skill" *ngFor="let employee of employees" (click)="changeEmployeeSkill(employee.id)">
<img src="assets/icons/done.svg" *ngIf="employeeIdsHasSkill.includes(employee.id); else noSkill">
<ng-template #noSkill><img class="square-img" src="assets/icons/icon_warning_red.svg"></ng-template>
<div class="skill-name"> {{employee.name}}</div>
</div>
</div>
header и sidebar
Довольно типовые для большинства проектов блоки, код можно посмотреть в исходниках проекта.
Прототип приложения на Angular написан, базовые навыки получены. Теперь можно приступить к React-проекту либо углубить текущий Angular-прототип, добавив в него авторизацию, админку, профили пользователей, красивые графики и прочую функциональность. Либо поработать с бекендом, заменив Firebase на полноценный микросервис на чём-нибудь современном, например, на fastAPI.
Как будем сравнивать?
Для начала попробуем написать на Angular простое приложение. Перед этим предлагаю прочитать базовые моменты из документации и пройти «Тур Героев». Получив основные навыки и взяв «Тур героев» за основу разработаем своё первое приложение на Angular и React, сравнив субьективные преимущества и недостатки.Описание проекта
В качестве первого приложения отлично подходят проекты вроде «список задач», «блог» или «учёт расходов». Чтобы не повторяться, попробуем создать приложение для выявления автобусного фактора в команде. Bus-фактор — то количество людей в проекте, внезапное исчезновение которых (например, из-за ДТП с автобусом) приведёт к остановке или значительному замедлению различных процессов.Приложение по аналогии с «Туром героев» будет состоять из главной dashboard-страницы, страницы с управлением навыками и сотрудниками, и с детализированными страницами по каждому навыку и сотруднику. Текущий дизайн приложения далёк от совершенства, основная цель — изучить логику работы с Angular и React при создании приложения.
На главной странице в MVP приложения выводим самых критичных сотрудников, чьи навыки надо забирать всей остальной команде
На странице с управлением навыками и сотрудниками мы увидим две колонки, в каждую из которых можно добавить новый навык или указать имя нового сотрудника. Навыком может быть как знание какой-то критически важной технологии, так и глубокое понимание работы того или иного микросервиса или фронт-проекта, эксплуатируемого командой. Для каждого навыка отображается, сколько сотрудников его знают, а для каждого сотрудника — количество освоенных им навыков.
Страницы с детализацией навыков и сотрудников похожи: на них можно отредактировать название навыка или имя сотрудника, а также нажатием на элемент из списка пометить, что сотрудник изучил навык (тогда красный восклицательный знак сменится на зелёную галочку).
Попробовать проект вживую можно вот тут: https://bus-factor.web.app, ссылка на кодовую базу — https://github.com/domclick/bus_factor
Описание кодовой базы и принятых решений
Чтобы при проектировании приложения не отвлекаться на написание любимого бекенда, был выбран Google Firebase как представитель Backend-as-a-service. Структура данных для проекта выглядит так:Всего две сущности — «Сотрудники» и их «Навыки», и таблица для прикрепления навыка к сотруднику. Для взаимодействия с этими сущностями были написаны мы написали Angular-сервисы, которые реализуют необходимый CRUD для общения с Firebase-бекендом:
Код
Описанный выше дизайн было решено реализовать на следующем наборе компонентов:
dashboard
Главная страница довольно простая, уместилась в один компонент. Чтобы одновременно загрузить данные и по сотрудникам, и по их связанным навыкам, используем forkJoin из rxjs. Полученные данные подготавливаем с помощью набора циклов и сортировки (которые наверняка можно было написать оптимальней), и получаем следующий файл:
Код
bus-factor-list
Страница для управления навыками и сотрудниками использует компоненты skill-item и employee-item. Для получения событий из дочерних компонентов и реакции на них используем директиву Output, обработав полученные данные в handleDeleteSkill и handleDeleteEmployee.
Код
В целом код для сущностей «Сотрудник» и «Навык» в MVP очень похож, но я не стал убирать дублирование кода, потому что в дальнейшем каждый компонент будет кастомизироваться. Typescript-логика для bus-factor-list выглядит так:
Код
skill-item
Для того, чтобы просклонять в зависимости от численности слово «сотрудник», был использован pipe pluralize:
Код
В компонент skill-item он подключается следующим образом:
<div class="skill-container" (click)="onSkillClick()">
<div class="skill-info">
<div class="skill-name">{{ skill.name }}</div>
<div class="skill-skills">
{{ skillCount }} {{ skillCount | pluralize: ['сотрудник', 'сотрудника', 'сотрудников'] }}
</div>
</div>
<button class="delete" title="delete skill"
(click)="deleteSkill(skill)">
Удалить
</button>
</div>
Внутри Typescript-логики можно увидеть использование события Output:
Код
skill-detail и employee-detail
На страницах с управлением навыками каждого сотрудника (employee-detail), а также на странице с редактированием навыка и списком сотрудников, обладающим этим навыком (skill-detail) можно увидеть использование директивы ng-template в else-блоке отображения наличия/отсутствия навыка:
<div class="card-title">Управление навыком</div>
<div class="skill-info">
<div class="skill-id"></div>
<input [(ngModel)]="skill.name" placeholder="Название навыка"/>
<div class="skill-controls">
<button (click)="goBack()">Назад</button>
<button (click)="save()">Сохранить</button>
</div>
</div>
<div class="skill-box">
<div class="skills-title">Сотрудники с этим навыком</div>
<div class="skill" *ngFor="let employee of employees" (click)="changeEmployeeSkill(employee.id)">
<img src="assets/icons/done.svg" *ngIf="employeeIdsHasSkill.includes(employee.id); else noSkill">
<ng-template #noSkill><img class="square-img" src="assets/icons/icon_warning_red.svg"></ng-template>
<div class="skill-name"> {{employee.name}}</div>
</div>
</div>
header и sidebar
Довольно типовые для большинства проектов блоки, код можно посмотреть в исходниках проекта.
Что дальше?
Прототип приложения на Angular написан, базовые навыки получены. Теперь можно приступить к React-проекту либо углубить текущий Angular-прототип, добавив в него авторизацию, админку, профили пользователей, красивые графики и прочую функциональность. Либо поработать с бекендом, заменив Firebase на полноценный микросервис на чём-нибудь современном, например, на fastAPI.
Angular vs React глазами новичка. Часть 1: Angular
В 2021 году на рынке фронтенд-технологий лидируют React, Angular и, с некоторым отставанием, Vue. В нашей компании для унификации подбора разработчиков сделан упор на React, но ряд крупных систем...
habr.com