Наша компания разрабатывает десятки продуктов. Ряд продуктов работает на Angular, ряд на React. Пользователи систем в зависимости от этапа бизнес-процесса и роли взаимодействует с определенным приложением. Часто, в рамках бизнеса мы должны показывать одни и те же данные в разных местах. Эти данные отображаются в виде UI компонентов.

В этой статье мы узнаем как можно организовать библиотеки компонентов для решения задач бизнеса. Научимся переиспользовать и запускать React компоненты внутри Angular. Таким способом мы сможем решать задачи бизнеса гибко и эффективно.

Допустим у нас есть 10 приложений. 3 на React, 7 на Angular. Мы выводим на экран информацию о пользователе в красивом компоненте:

  • ФИО

  • Контактный телефон

  • Почта

  • Число сделок

  • Список меток (новый пользователь, частый клиент)

Через месяц приходит бизнес и ставит задачу добавить еще 1 поле в компонент.

Первый сценарий развития (да, такое бывает - дикий запад)

Команды разрознены. Каждая из них разрабатывает свое приложение и держит компоненты прямо в проекте. Что происходит при доработках:

  • Заходим в каждый проект в отдельности и дорабатываем компоненты

Получается достаточно накладно по времени. Совершить одни и те же действия N раз.

Второй сценарий развития (частый сценарий)

Деление на React и Angular пакетную базу. Это более позитивный сценарий. В этом случае есть некий UIKit для двух фронтенд инструментов. Работа будет сводиться к следующим действиям:

  • Дорабатываем компонент на React

  • Публикуем React пакет

  • Обновляем зависимость в React приложениях

  • Дорабатываем компонент на Angular

  • Публикуем пакет на Angular

  • Обновляем зависимость в Anguar приложениях

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

Третий подход о котором я расскажу: основной пакет - много приложений

Его подход заключается в следующем:

  • Пишем компонент на React

  • Добавляем Angular прослойку для React компонента (прокидываем props через Input декораторы) - проект library.

  • Одной командой публикуем 2 пакета

  • Обновляем приложения

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

Код компонента Angular использующий React:

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

import { AfterViewInit, Component, Input, NgZone, OnChanges, OnInit } from '@angular/core';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Avatar, { ReactAvatarProps } from 'react-avatar';

@Component({
  selector: 'app-ng-avatar',
  templateUrl: './ng-avatar.component.html'
})
export class NgAvatarComponent implements OnChanges, AfterViewInit {
	containerId: string = 'avatar-xxxxxxxx'.replace(/[x]/g, c => (Math.random() * 16 | 0).toString(16));
  
  @Input()
  name: string = '';
  @Input()
  round: string = '';
  @Input()
  color?: string = undefined;

  constructor(private _ngZone: NgZone) { }

  ngOnInit() {
  }
  ngAfterViewInit() {
    this.render();
  }

  ngOnChanges() {
      this.render();
  }

  render = () => {
    const props: ReactAvatarProps = {
      name: this.name,
      round: this.round,
      color: this.color
    };

    if (document.getElementById(this.containerId)) {
      this._ngZone.runOutsideAngular(
      	() => {
          ReactDOM.render(React.createElement(Avatar, props),
            document.getElementById(this.containerId)
          );
        }
      );
    }
  }
}

Результат работы:

react-avatar in angular
react-avatar in angular

Плюсы для бизнеса

  • Более быстрое получение UI фичи

  • Меньше времени на синхронизацию команд

  • Единый стиль в продуктах

Плюсы для команд

  • Экспертиза в разных инструментах

Заключение

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

Ссылка на Githib с примером
Ссылка на статью - создание библиотеки компонентов на примере иконок

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


  1. JustDont
    17.09.2021 14:05
    +1

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


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


    1. alexbraun Автор
      17.09.2021 14:24
      +1

      Спасибо за рекомендацию посмотреть в сторону framework-agnostic.
      Да тут есть минусы размера. Мы используем данный подход только для проектов Middle и Бек офис. В публичных приложений используется SSR и там следят за размером бандла.


  1. chemaxa
    17.09.2021 14:13
    +1

    Интересный подход, а не пробовали https://developer.mozilla.org/ru/docs/Web/Web_Components их вроде как можно написать, и потом просто подключить в ангуляр и в реакт и вообще куда угодно написав небольшой адаптер под нужный фреймворк? Вы рассматривали такой подход?

    Я сам не пробовал, но гипотеза кажется рабочей.


    1. JustDont
      17.09.2021 14:20
      +3

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


      Ну и подключать веб-компоненты в реакт — не самая простая история, потому что реакт как обычно отличился, и не желает быть гладко совместимым (см. https://custom-elements-everywhere.com/)


      1. alexbraun Автор
        17.09.2021 14:37

        те из популярных инструментов только реакт пока не полностью совместим?


        1. JustDont
          17.09.2021 14:47
          +2

          Оно совместимо (там по ссылке можно увидеть, что "basic tests" все проходят, и принципиальную подключаемость это уже даст), просто придётся руками разруливать все открытые вопросы. А не то, что привязал входы-выходы, и всё сразу взлетело.


          С вебкомпонентами проблема в них самих — это будет третья технология, которую надо будет правильно запустить (в связках реакт-wc и ангуляр-wc), и скользкие моменты там естественно есть, особенно если отойти в сторону от обычных взаимодействий. Я, например, как-то раз обнаружил, что инициализация веб-компонентов при переносе DOM с ними между страницами — настолько дико отличается в ФФ и Хроме (Хром, как обычно, имеет собственное мнение на счёт того, как всё должно быть), что код, нормальный для одного случая, просто непоправимо падает в другом, и наоборот.
          Хотя, конечно, кому "в распространенных ситуациях" надо переносить DOM между страницами?


          1. alexbraun Автор
            17.09.2021 14:54

            Да, каждый браузер по своему реализует веб стандарты.
            А в какой ситуации нужно переносить DOM между страницами? Стало интересно.


            1. JustDont
              17.09.2021 15:02

              А в какой ситуации нужно переносить DOM между страницами? Стало интересно.

              Так делает wkhtmltopdf — создаёт клон страницы, а потом перегоняет его в pdf.


      1. bouncycastle
        18.09.2021 01:52

        Помню слышал на одном докладе про ангуляр, слышал что есть возможность экспортировать компонент как web component


    1. alexbraun Автор
      17.09.2021 14:34
      +1

      Мы начинали работать в этом подходе несколько лет назад, тогда Angular еще не предоставил АПИ для создания веб компонентов. Поэтому пошли наиболее удобным способом для нас. Недавно делал доработки в react библиотеке и был доволен как просто я обновил еще десяток приложений, поэтому решил поделиться.
      Знаю что кто-то исследовал возможность веб компонентов, но до практики не дошли.


      1. justboris
        17.09.2021 16:03
        +1

        Веб-компоненты как стандарт зародился более 10 лет назад, и с тех пор современные подходы улетели далеко вперед, а веб-компоненты все никак не угонятся и по-прежнему предоставляют удобство на уровне AngularJS.

        Поэтому когда мне предлагают написать что-то на веб-компонентах, я смотрю на это как на шаг назад.


  1. kemsky
    17.09.2021 14:53
    +1

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


  1. justboris
    17.09.2021 16:05
    +2

    Еще есть 4й вариант – собраться с силами и принять корпоративный стандарт по технологиям, и закончить с этим зоопарком.


    1. alexbraun Автор
      17.09.2021 17:19

      У нас диверсификация и живем дружно.


      1. justboris
        17.09.2021 17:20

        Изначально вопрос стоял "как извлечь максимальную пользу для бизнеса". С этой точки зрения разнообразие фреймворков только идёт в минус


        1. alexbraun Автор
          17.09.2021 17:30
          +1

          Согласен, разнообразие не лучшее, что может быть. Хорошо стартовать в 2021 году новые проекты с твердой позицией. Но вернуться в 2016 и перепиливать бизнес приложения с 1 технологии на другую тоже процесс не легкий, сделано много. А так react свежий, angular тоже. Всем комфортно.


        1. JustDont
          17.09.2021 17:55

          Кстати, совершенно необязательно.
          То есть да, в 2021 году брать и реакт и ангуляр — ну, уже такое. А вот в 2015 году этот вопрос совсем иначе выглядит. Точно так же, как в 2021 году выглядит другой bleeding edge (на фронте ситуация с бесконечными новыми нескучными фреймворками сейчас чуть поутихла, но вот в девопс вроде самое оно творится).
          А если брать что-то одно и твёрдо в него вписываться — можно потом оказаться компанией Wrike с её dart. И что-то это уже на максимальную пользу для бизнеса не тянет.


          1. alexbraun Автор
            17.09.2021 18:04

            Знаю ребят, которые пытаются полностью уйти на Flutter (ios, android) и Flutter web. Это Dart, интересно их будущее.


  1. ravendyg
    23.09.2021 07:16

    Я правильно понимаю, что у вас при каждом изменении Input вложенный реакт компонент монтируется заново. Т.е. такую обёртку можно использовать только с чем-то примитивным?
    Что произойдёт если вовнутрь засунуть что-нибудь сложное, требующее загрузки начального состояния.