Или как мы реализовали нашу архитектуру Micro Frontend, используя плагины webpack и простую структуру данных.

Jahia 8 представляет новый пользовательский интерфейс, полностью основанный на React. Когда мы начали создавать архитектуру для этого пользовательского интерфейса, у нас было главное требование: иметь полностью модульный пользовательский интерфейс, который мог бы быть расширен нами или нашими пользователями. В предыдущих версиях пользовательский интерфейс, созданный с помощью GWT, представлял собой монолит JS - все компилировалось в одном месте, содержало полный интерфейс, не давая возможности его впоследствии расширять. Добавление любого виджета в пользовательский интерфейс потребовало полной перекомпиляции всего пользовательского интерфейса.

Вы сказали "микро-интерфейсы"?

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

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

Нашими основными целями были:

  • Поделитесь набором общих библиотек, чтобы не перезагружать их несколько раз. Во всем приложении используются React, apollo-graphql, компоненты системы проектирования и другие полезные библиотеки.
  • Поделитесь некоторыми структурами данных. Например, единое хранилище redux, которое может использоваться всеми частями.
  • Уметь динамически добавлять новые части, которые могут расширять приложение. Эти новые части необходимо компилировать и выпускать независимо от других.
  • Иметь интегрированный пользовательский интерфейс - нам не обязательно смешивать разные фреймворки. Нам скорее нужна тесная интеграция между частями приложения, где каждая может расширять другую.
  • Повторно используйте одну и ту же систему дизайна: все части приложения должны использовать одну и ту же систему дизайна и обеспечивать визуальную согласованность.

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

Оболочка приложения - на помощь приходит webpack

Webpack предоставляет интересный плагин, который помогает нам разделить код нашего приложения на несколько пакетов: плагин DLL и его аналог плагин ссылки на DLL. Этот плагин позволяет разделить компиляцию вашего приложения на разные части. Первоначальная идея заключалась в том, чтобы ускорить разработку: вместо того, чтобы каждый раз повторно упаковывать ваше приложение со всеми его зависимостями, вы могли создать первый пакет «DLL» веб-пакета со всеми зависимостями (в основном библиотеки поставщиков) и запускать веб-пакет только на ваши собственные источники. Плагин DLL создает пакет JS без какого-либо кода начальной загрузки и добавляет его как библиотеку в окно. Он также сгенерирует файл манифеста, содержащий все доступные модули, который будет использоваться подключаемым модулем ссылки DLL. Этот плагин в основном создает внешние ссылки на первый пакет для модулей, доступных в библиотеке.

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

Наша оболочка приложения содержит 2 разные конфигурации веб-пакетов: одну для «обычных» библиотек и одну для начальной загрузки приложения.

Часть общих ресурсов использует подключаемый модуль DLL для создания библиотеки «jahiaCommons» в пакете. Эта библиотека содержит всю общую структуру, которую мы разделяем в приложении, и которую мы не хотим загружать несколько раз. jahiaCommons доступен в объекте окна и будет использоваться всеми другими пакетами с помощью подключаемого модуля ссылки DLL, указывающего на него. Компиляция также генерирует манифест DLL, содержащий список всех модулей, присутствующих в пакете.

Приложение инициализирует разные фреймворки, а также загрузит и загрузит различные зарегистрированные пакеты. Все они могут использовать библиотеки в jahiaCommons.

Собираем все вместе - реестр

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

Реестр является частью пакета «jahiaCommons», поэтому его данные совместно используются и доступны для всех других пакетов. Он может содержать любой объект JS - им просто нужен уникальный ключ, идентификатор типа («app», «route»,…) и «цель». сообщая, где этот объект следует использовать. В дополнение к этому они могут добавлять любые другие полезные данные, от простого текста до полноценного компонента реакции. Кстати, вам не нужно писать код React, чтобы что-то поместить в реестр - вам даже не нужно использовать webpack. В зависимости от типа расширения, которое вы хотите написать, вы можете использовать простой JS или полный пакет webpack / response.

Основной компонент React «App» хранится в реестре, поэтому оболочку приложения можно использовать для рендеринга нескольких приложений на основе разных пакетов. Кроме того, пакет может зарегистрировать «поставщика» React, обертывающего основной компонент, предоставляемый другим пакетом.

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

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

Распространенным расширением является добавление простой кнопки в приложение, например, записи в главном меню или на верхней панели - все эти кнопки берутся из реестра, а цель определяет, где они должны появиться. Они могут быть написаны как компонент React или как простая функция JS, вызываемая при нажатии кнопки.

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

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

Играть с этим

Все концепции, подробно описанные в этой статье, были реализованы для Jahia 8. И, поскольку они являются частью кодовой базы с открытым исходным кодом, вы можете ознакомиться с нашей точной реализацией здесь:

И сейчас ?

С тех пор мы переключили реализацию на Webpack 5 и используем Module Federation:



дальнейшее чтение